diff --git a/android/assets/fonts/PatrickHand.ttf b/android/assets/fonts/PatrickHand.ttf new file mode 100644 index 0000000..7528dcd Binary files /dev/null and b/android/assets/fonts/PatrickHand.ttf differ diff --git a/build.gradle b/build.gradle index 0514342..8d82a6e 100644 --- a/build.gradle +++ b/build.gradle @@ -56,7 +56,13 @@ project(":android") { natives "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-x86" natives "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-x86_64" compile "com.badlogicgames.ashley:ashley:$ashleyVersion" - + + compile "com.badlogicgames.gdx:gdx-freetype:$gdxVersion" + natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-armeabi" + natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-armeabi-v7a" + natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-arm64-v8a" + natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-x86" + natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-x86_64" } } @@ -68,7 +74,7 @@ project(":core") { compile "com.badlogicgames.gdx:gdx:$gdxVersion" compile "com.badlogicgames.gdx:gdx-box2d:$gdxVersion" compile "com.badlogicgames.ashley:ashley:$ashleyVersion" - + compile "com.badlogicgames.gdx:gdx-freetype:$gdxVersion" } } diff --git a/core/src/com/mdibaiee/supersnake/Colors.java b/core/src/com/mdibaiee/supersnake/Colors.java index da696dd..4bbc2d1 100644 --- a/core/src/com/mdibaiee/supersnake/Colors.java +++ b/core/src/com/mdibaiee/supersnake/Colors.java @@ -7,4 +7,5 @@ public class Colors { static public Color snake = new Color(0, 0.9f, 0.7f, 1); static public Color ball = new Color(1, 0.4f, 0, 1); static public Color red = new Color(1, 0.34f, 0, 1); + static public Color spray = new Color(0.36f, 0.74f, 0.8f, 1); } diff --git a/core/src/com/mdibaiee/supersnake/Magic.java b/core/src/com/mdibaiee/supersnake/Magic.java index dfd3e87..4ed67d2 100644 --- a/core/src/com/mdibaiee/supersnake/Magic.java +++ b/core/src/com/mdibaiee/supersnake/Magic.java @@ -4,6 +4,7 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.glutils.ShapeRenderer; +import com.badlogic.gdx.utils.Array; public abstract class Magic extends SizedPoint { SpriteBatch batch; @@ -67,7 +68,7 @@ public abstract class Magic extends SizedPoint { return false; } - abstract public void action(Snake snake); + abstract public void action(Snake snake, Array magics); // this method will be called after action at each iteration until it returns true // when it does return true ,the object is disposed diff --git a/core/src/com/mdibaiee/supersnake/Magics/Flip.java b/core/src/com/mdibaiee/supersnake/Magics/Flip.java new file mode 100644 index 0000000..d64f923 --- /dev/null +++ b/core/src/com/mdibaiee/supersnake/Magics/Flip.java @@ -0,0 +1,33 @@ +package com.mdibaiee.supersnake.Magics; + +import com.badlogic.gdx.utils.Array; +import com.mdibaiee.supersnake.Magic; +import com.mdibaiee.supersnake.Snake; + + +public class Flip extends Magic { + private Snake snake; + + public Flip(float x, float y) { + super(x, y, "spiral.png"); + } + + public void action(Snake snake, Array magics) { + for (int i = 0; i < magics.size; i++) { + Magic m = magics.get(i); + m.move(m.y, m.x); + } + + this.snake = snake; + } + + public boolean draw() { + rotation = drawn % 360; + + return super.draw(); + } + + public boolean iter() { + return true; + } +} diff --git a/core/src/com/mdibaiee/supersnake/Magics/Growth.java b/core/src/com/mdibaiee/supersnake/Magics/Growth.java index ac432bd..1f2d5b7 100644 --- a/core/src/com/mdibaiee/supersnake/Magics/Growth.java +++ b/core/src/com/mdibaiee/supersnake/Magics/Growth.java @@ -1,5 +1,6 @@ package com.mdibaiee.supersnake.Magics; +import com.badlogic.gdx.utils.Array; import com.mdibaiee.supersnake.Magic; import com.mdibaiee.supersnake.Snake; @@ -11,7 +12,7 @@ public class Growth extends Magic { super(x, y, "blue.png"); } - public void action(Snake snake) { + public void action(Snake snake, Array magics) { this.snake = snake; snake.size += 10; } diff --git a/core/src/com/mdibaiee/supersnake/Magics/Skull.java b/core/src/com/mdibaiee/supersnake/Magics/Skull.java index 1a94bcb..1e53a15 100644 --- a/core/src/com/mdibaiee/supersnake/Magics/Skull.java +++ b/core/src/com/mdibaiee/supersnake/Magics/Skull.java @@ -1,19 +1,29 @@ package com.mdibaiee.supersnake.Magics; +import com.badlogic.gdx.utils.Array; import com.mdibaiee.supersnake.Colors; import com.mdibaiee.supersnake.Magic; import com.mdibaiee.supersnake.Snake; public class Skull extends Magic { private Snake snake; - private int seconds = 15; + private int seconds = 7; + private int original_points; public Skull(float x, float y) { super(x, y, "skull.png"); } - public void action(Snake snake) { + public boolean draw() { + float rx = (float) Math.random() * 30 - 15; + rotation = rx; + + return super.draw(); + } + + public void action(Snake snake, Array magics) { this.snake = snake; + original_points = snake.point; snake.color = Colors.red; } @@ -22,6 +32,7 @@ public class Skull extends Magic { if (frames > seconds * 60) { snake.color = Colors.snake; + if (snake.point <= original_points) { snake.lives -= 1; } return true; } diff --git a/core/src/com/mdibaiee/supersnake/Magics/SpeedBoost.java b/core/src/com/mdibaiee/supersnake/Magics/SpeedBoost.java index 93153d2..e96c1eb 100644 --- a/core/src/com/mdibaiee/supersnake/Magics/SpeedBoost.java +++ b/core/src/com/mdibaiee/supersnake/Magics/SpeedBoost.java @@ -1,5 +1,6 @@ package com.mdibaiee.supersnake.Magics; +import com.badlogic.gdx.utils.Array; import com.mdibaiee.supersnake.Magic; import com.mdibaiee.supersnake.Snake; @@ -16,7 +17,7 @@ public class SpeedBoost extends Magic { original_y = y; } - public void action(Snake snake) { + public void action(Snake snake, Array magics) { this.snake = snake; snake.speed += 5; } diff --git a/core/src/com/mdibaiee/supersnake/Magics/StarPoint.java b/core/src/com/mdibaiee/supersnake/Magics/StarPoint.java index 1a2ef22..633ebb6 100644 --- a/core/src/com/mdibaiee/supersnake/Magics/StarPoint.java +++ b/core/src/com/mdibaiee/supersnake/Magics/StarPoint.java @@ -2,6 +2,8 @@ package com.mdibaiee.supersnake.Magics; import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.utils.Array; +import com.mdibaiee.supersnake.Colors; import com.mdibaiee.supersnake.Magic; import com.mdibaiee.supersnake.Snake; @@ -16,8 +18,14 @@ public class StarPoint extends Magic { return super.draw(); } - public void action(Snake snake) { + public void action(Snake snake, Array magics) { snake.point++; + + if (snake.color != Colors.snake) { + snake.point++; + } + + snake.color = Colors.snake; snake.addTail(); } diff --git a/core/src/com/mdibaiee/supersnake/Snake.java b/core/src/com/mdibaiee/supersnake/Snake.java index 6fcb5e1..8d3b15e 100644 --- a/core/src/com/mdibaiee/supersnake/Snake.java +++ b/core/src/com/mdibaiee/supersnake/Snake.java @@ -31,7 +31,7 @@ public class Snake extends DirectedPoint { private Array tail = new Array(); - public float speed = 2; + public float speed = 4; public int lives = 3; public Snake(float x, float y, int length) { @@ -89,7 +89,7 @@ public class Snake extends DirectedPoint { boolean cycled = this.move(x + cx(direction) * speed, y + cy(direction) * speed); - Gdx.app.log("Snake", "(" + ox + ", " + oy + ") > " + "(" + x + ", " + y + ")"); + // Gdx.app.log("Snake", "(" + ox + ", " + oy + ") > " + "(" + x + ", " + y + ")"); if (cycled) { tail.insert(0, new Tail(ox, oy, direction, 0)); @@ -112,11 +112,15 @@ public class Snake extends DirectedPoint { public void addTail() { Tail last = tail.peek(); - last.length += 5; - last.x -= cx(last.direction) * 5; - last.y -= cy(last.direction) * 5; + last.length += 25; + last.x -= cx(last.direction) * 25; + last.y -= cy(last.direction) * 25; - speed += 0.5; + speed += 1; + } + + public void clearTail() { + tail.removeRange(1, tail.size); } public boolean head_collision(SizedPoint p) { diff --git a/core/src/com/mdibaiee/supersnake/SuperSnake.java b/core/src/com/mdibaiee/supersnake/SuperSnake.java index b56ad3e..6b03aad 100644 --- a/core/src/com/mdibaiee/supersnake/SuperSnake.java +++ b/core/src/com/mdibaiee/supersnake/SuperSnake.java @@ -1,4 +1,7 @@ package com.mdibaiee.supersnake; +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator; +import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator.FreeTypeFontParameter; import com.mdibaiee.supersnake.Magics.*; import com.badlogic.gdx.ApplicationAdapter; @@ -14,38 +17,103 @@ public class SuperSnake extends ApplicationAdapter { public int WIDTH = 800; public int HEIGHT = 480; + private int PADDED_WIDTH; + private int PADDED_HEIGHT; + private int PADDING = 20; + + private int INITIAL_SNAKE_LENGTH = 70; + + private boolean paused; + SpriteBatch batch; ShapeRenderer shapeRenderer; Texture img; Snake snake; BitmapFont font; + BitmapFont fontBig; + BitmapFont fontBtn; + + Snake pause_snake; + private int pause_frames = 0; + + private int gameover_timer = 3 * 60; private Array magics = new Array(); @Override public void create () { batch = new SpriteBatch(); - font = new BitmapFont(); WIDTH = Gdx.graphics.getBackBufferWidth(); HEIGHT = Gdx.graphics.getBackBufferHeight(); + PADDED_WIDTH = WIDTH - PADDING; + PADDED_HEIGHT = HEIGHT - PADDING; + Gdx.app.log("Snake", "VIEWPORT " + WIDTH + ", " + HEIGHT); shapeRenderer = new ShapeRenderer(); - snake = new Snake(WIDTH / 2, HEIGHT / 2, 50); + snake = new Snake(WIDTH / 2, HEIGHT / 2, INITIAL_SNAKE_LENGTH); + pause_snake = new Snake(WIDTH / 2, 200, 100); + + FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/PatrickHand.ttf")); + FreeTypeFontParameter parameter = new FreeTypeFontParameter(); + parameter.size = 32; + font = generator.generateFont(parameter); + + parameter.size = 52; + parameter.borderColor = Colors.spray; + parameter.borderWidth = 2; + fontBtn = generator.generateFont(parameter); + + parameter.size = 80; + parameter.color = Color.WHITE; + parameter.borderWidth = 2; + parameter.borderColor = Colors.red; + fontBig = generator.generateFont(parameter); + + generator.dispose(); } + private Point random_point() { + float rx = (float) Math.random() * PADDED_WIDTH + PADDING; + float ry = (float) Math.random() * PADDED_HEIGHT + PADDING; + + return new Point(rx, ry); + } + + private Direction random_direction() { + double r = Math.random() * 100; + if (r < 25) { + return Direction.Down; + } else if (r < 50) { + return Direction.Up; + } else if (r < 75) { + return Direction.Left; + } else { + return Direction.Right; + } + } + @Override public void render () { Gdx.gl.glClearColor(Colors.background.r, Colors.background.g, Colors.background.b, Colors.background.a); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); + if(Gdx.input.justTouched()) { float x = Gdx.input.getX(); float y = Gdx.input.getY(); + if (x > WIDTH - 150 && y > HEIGHT - 60) { + paused = true; + return; + } else if (paused) { + paused = false; + return; + } + if (snake.direction == Direction.Left || snake.direction == Direction.Right) { if (y < HEIGHT / 2) { snake.setDirection(Direction.Up); @@ -61,6 +129,54 @@ public class SuperSnake extends ApplicationAdapter { } } + if (paused) { + batch.begin(); + fontBtn.draw(batch, "Super Snake", WIDTH / 2 - 125, HEIGHT - 150); + + font.draw(batch, "Simple, fast-paced snake game packed with extra fun!", WIDTH / 2 - 300, HEIGHT - 250); + font.draw(batch, "by Mahdi Dibaiee", WIDTH / 2 - 100, HEIGHT - 300); + + font.draw(batch, "Source code available on", WIDTH / 2 - 135, HEIGHT - 400); + font.draw(batch, "github.com/mdibaiee/super-snake", WIDTH / 2 - 200, HEIGHT - 450); + + font.draw(batch, "Powered by LibGDX", WIDTH / 2 - 120, 150); + batch.end(); + + pause_snake.draw(shapeRenderer); + pause_snake.move(); + + int luck = (int) (Math.random() * 30 - 15); + if (pause_frames % (20 + luck) == 0) { + pause_snake.setDirection(random_direction()); + } + + if (pause_frames % (250 + luck) == 0 && pause_frames < 1000) { + pause_snake.addTail(); + } + + pause_frames++; + + return; + } + + if (snake.isDead()) { + batch.begin(); + fontBig.draw(batch, "Game Over", WIDTH / 2 - 160, HEIGHT / 2 + 40); + String seconds = String.format("%.1f", gameover_timer / 60f); + font.draw(batch, seconds, WIDTH / 2 - 10, HEIGHT / 2 - 50); + gameover_timer -= 1; + batch.end(); + + if (gameover_timer <= 0) { + Point r = random_point(); + snake = new Snake(r.x, r.y, INITIAL_SNAKE_LENGTH); + magics.clear(); + gameover_timer = 3 * 60; + } + + return; + } + int drawn_magics = 0; for (Magic m: magics) { @@ -68,23 +184,24 @@ public class SuperSnake extends ApplicationAdapter { } if (drawn_magics < 3) { + double r = Math.random() * 100; - float mx = (float) Math.random() * WIDTH; - float my = (float) Math.random() * HEIGHT; + + Point p = random_point(); Magic newMagic; - if (r < 70) { - newMagic = new StarPoint(mx, my); + if (r < 60) { + newMagic = new StarPoint(p.x, p.y); + } else if (r < 70) { + newMagic = new SpeedBoost(p.x, p.y); } else if (r < 80) { - newMagic = new SpeedBoost(mx, my); + newMagic = new Growth(p.x, p.y); } else if (r < 90) { - newMagic = new Growth(mx, my); + newMagic = new Skull(p.x, p.y); } else { - newMagic = new Skull(mx, my); + newMagic = new Flip(p.x, p.y); } - newMagic = new SpeedBoost(mx, my); - magics.add(newMagic); } @@ -100,14 +217,17 @@ public class SuperSnake extends ApplicationAdapter { if (m.draw()) { magics.removeValue(m, true); } else if (snake.head_collision(m)) { - m.action(snake); + m.action(snake, magics); m.active = true; } } } batch.begin(); - font.draw(batch, Integer.toString(snake.point), 10, 25); + font.draw(batch, "Points: " + snake.point, 20, 35); + font.draw(batch, "Lives: " + snake.lives, 150, 35); + + font.draw(batch, "About", WIDTH - 90, 35); batch.end(); }