diff --git a/Knuckle's Adventure/.classpath b/Knuckle's Adventure/.classpath
new file mode 100644
index 0000000..b8cca6f
--- /dev/null
+++ b/Knuckle's Adventure/.classpath
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/Knuckle's Adventure/.gitignore b/Knuckle's Adventure/.gitignore
new file mode 100644
index 0000000..5e56e04
--- /dev/null
+++ b/Knuckle's Adventure/.gitignore
@@ -0,0 +1 @@
+/bin
diff --git a/Knuckle's Adventure/.project b/Knuckle's Adventure/.project
new file mode 100644
index 0000000..de9d52b
--- /dev/null
+++ b/Knuckle's Adventure/.project
@@ -0,0 +1,17 @@
+
+
+ Dragon Tale Tutorial
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Knuckle's Adventure/.settings/org.eclipse.jdt.core.prefs b/Knuckle's Adventure/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..e179d4e
--- /dev/null
+++ b/Knuckle's Adventure/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,12 @@
+#Sat Apr 13 11:56:25 EDT 2013
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/Knuckle's Adventure/Libs/jl1.0.1.jar b/Knuckle's Adventure/Libs/jl1.0.1.jar
new file mode 100644
index 0000000..bd5fb8b
Binary files /dev/null and b/Knuckle's Adventure/Libs/jl1.0.1.jar differ
diff --git a/Knuckle's Adventure/Libs/mp3spi1.9.5.jar b/Knuckle's Adventure/Libs/mp3spi1.9.5.jar
new file mode 100644
index 0000000..0c74dae
Binary files /dev/null and b/Knuckle's Adventure/Libs/mp3spi1.9.5.jar differ
diff --git a/Knuckle's Adventure/Libs/tritonus_share.jar b/Knuckle's Adventure/Libs/tritonus_share.jar
new file mode 100644
index 0000000..d21ba89
Binary files /dev/null and b/Knuckle's Adventure/Libs/tritonus_share.jar differ
diff --git a/Knuckle's Adventure/Resources/Backgrounds/SunSetHill1.gif b/Knuckle's Adventure/Resources/Backgrounds/SunSetHill1.gif
new file mode 100644
index 0000000..de357dc
Binary files /dev/null and b/Knuckle's Adventure/Resources/Backgrounds/SunSetHill1.gif differ
diff --git a/Knuckle's Adventure/Resources/HUD/hud.gif b/Knuckle's Adventure/Resources/HUD/hud.gif
new file mode 100644
index 0000000..b50cf19
Binary files /dev/null and b/Knuckle's Adventure/Resources/HUD/hud.gif differ
diff --git a/Knuckle's Adventure/Resources/Maps/level1-1.map b/Knuckle's Adventure/Resources/Maps/level1-1.map
new file mode 100644
index 0000000..c5648d5
--- /dev/null
+++ b/Knuckle's Adventure/Resources/Maps/level1-1.map
@@ -0,0 +1,10 @@
+107
+8
+22 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22
+22 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 18 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 19 17 17 17 17 17 17 17 17 17 18 22 22 22 22 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 18 22 22 22 22 22 19 17 17 17 17 17 17 17 18 22
+22 4 0 0 0 0 0 0 0 0 0 0 13 0 0 0 0 0 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 0 0 0 0 17 17 17 18 22 22 22 22 22 22 22 22 22 22 22 4 0 0 16 0 0 0 0 0 0 0 17 18 22 22 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 18 22 22 22 22 4 0 0 0 0 0 0 0 3 22
+22 4 0 0 0 0 0 0 0 0 0 0 0 0 0 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 11 0 0 0 0 23 24 25 0 0 0 0 0 0 0 17 17 18 22 22 22 22 22 22 22 19 0 0 10 0 11 0 0 0 0 0 0 0 0 17 17 0 0 0 0 9 0 0 0 0 1 21 2 0 0 0 0 0 0 18 22 22 22 4 0 0 0 0 0 0 0 3 22
+22 4 0 0 0 12 0 0 0 0 0 0 11 1 21 21 2 0 0 0 0 0 0 0 0 0 0 15 0 0 0 0 0 23 25 0 0 0 0 0 0 0 0 0 0 9 11 0 0 0 0 0 17 17 17 17 17 17 17 0 0 1 21 21 21 2 0 0 0 0 0 0 0 0 0 0 0 0 0 23 24 25 0 0 3 22 4 0 0 0 0 0 0 0 18 22 22 4 0 0 0 0 0 0 0 3 22
+22 4 0 0 0 0 0 0 0 0 1 21 21 21 6 22 4 0 0 0 0 0 10 9 0 0 0 0 0 0 10 0 0 0 0 0 0 11 0 0 0 0 0 1 21 21 21 21 2 0 0 0 9 0 0 0 0 9 0 0 0 3 22 22 22 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 22 4 0 0 0 0 0 0 0 0 17 17 0 0 0 0 0 0 0 0 3 22
+22 4 9 0 10 0 0 0 0 11 3 22 22 22 22 22 4 0 0 0 1 21 21 21 21 2 0 0 9 1 21 21 2 0 9 1 21 21 2 0 0 0 0 3 22 22 22 22 4 10 0 1 21 2 0 0 1 21 2 11 1 21 6 22 22 4 0 0 0 0 0 0 0 9 0 0 10 9 0 0 11 0 0 1 21 5 21 2 0 0 0 0 0 0 0 0 0 0 0 10 11 0 0 9 0 3 22
+5 21 21 21 21 21 21 21 21 21 21 6 22 22 22 22 4 0 0 0 3 22 22 22 22 21 21 21 21 21 6 5 21 21 21 21 6 22 4 0 0 0 0 3 22 22 22 5 21 21 21 21 21 21 21 21 21 21 21 21 21 6 22 22 22 4 0 0 0 0 0 1 21 21 21 21 21 21 21 21 21 21 21 21 6 22 5 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 6
diff --git a/Knuckle's Adventure/Resources/Menu/Emblem.gif b/Knuckle's Adventure/Resources/Menu/Emblem.gif
new file mode 100644
index 0000000..9668946
Binary files /dev/null and b/Knuckle's Adventure/Resources/Menu/Emblem.gif differ
diff --git a/Knuckle's Adventure/Resources/Menu/Emblem2.gif b/Knuckle's Adventure/Resources/Menu/Emblem2.gif
new file mode 100644
index 0000000..0afbb32
Binary files /dev/null and b/Knuckle's Adventure/Resources/Menu/Emblem2.gif differ
diff --git a/Knuckle's Adventure/Resources/Menu/Island_Background.gif b/Knuckle's Adventure/Resources/Menu/Island_Background.gif
new file mode 100644
index 0000000..9d20fab
Binary files /dev/null and b/Knuckle's Adventure/Resources/Menu/Island_Background.gif differ
diff --git a/Knuckle's Adventure/Resources/Menu/Island_Background2.gif b/Knuckle's Adventure/Resources/Menu/Island_Background2.gif
new file mode 100644
index 0000000..70151a7
Binary files /dev/null and b/Knuckle's Adventure/Resources/Menu/Island_Background2.gif differ
diff --git a/Knuckle's Adventure/Resources/Music/EmeraldHillZone.mp3 b/Knuckle's Adventure/Resources/Music/EmeraldHillZone.mp3
new file mode 100644
index 0000000..8a72963
Binary files /dev/null and b/Knuckle's Adventure/Resources/Music/EmeraldHillZone.mp3 differ
diff --git a/Knuckle's Adventure/Resources/Music/IceCapZone.mp3 b/Knuckle's Adventure/Resources/Music/IceCapZone.mp3
new file mode 100644
index 0000000..7171ae1
Binary files /dev/null and b/Knuckle's Adventure/Resources/Music/IceCapZone.mp3 differ
diff --git a/Knuckle's Adventure/Resources/Music/Intro.mp3 b/Knuckle's Adventure/Resources/Music/Intro.mp3
new file mode 100644
index 0000000..ea3f477
Binary files /dev/null and b/Knuckle's Adventure/Resources/Music/Intro.mp3 differ
diff --git a/Knuckle's Adventure/Resources/Music/Sonic The Hedgehog 2 HD intro alternate version.mp3 b/Knuckle's Adventure/Resources/Music/Sonic The Hedgehog 2 HD intro alternate version.mp3
new file mode 100644
index 0000000..f3e5f5a
Binary files /dev/null and b/Knuckle's Adventure/Resources/Music/Sonic The Hedgehog 2 HD intro alternate version.mp3 differ
diff --git a/Knuckle's Adventure/Resources/Music/Tee.mp3 b/Knuckle's Adventure/Resources/Music/Tee.mp3
new file mode 100644
index 0000000..8a72963
Binary files /dev/null and b/Knuckle's Adventure/Resources/Music/Tee.mp3 differ
diff --git a/Knuckle's Adventure/Resources/SFX/jump.mp3 b/Knuckle's Adventure/Resources/SFX/jump.mp3
new file mode 100644
index 0000000..46c3fe0
Binary files /dev/null and b/Knuckle's Adventure/Resources/SFX/jump.mp3 differ
diff --git a/Knuckle's Adventure/Resources/SFX/punch.mp3 b/Knuckle's Adventure/Resources/SFX/punch.mp3
new file mode 100644
index 0000000..edfdadb
Binary files /dev/null and b/Knuckle's Adventure/Resources/SFX/punch.mp3 differ
diff --git a/Knuckle's Adventure/Resources/Sprites/Enemies/Motobug-sprite.gif b/Knuckle's Adventure/Resources/Sprites/Enemies/Motobug-sprite.gif
new file mode 100644
index 0000000..5c8a73c
Binary files /dev/null and b/Knuckle's Adventure/Resources/Sprites/Enemies/Motobug-sprite.gif differ
diff --git a/Knuckle's Adventure/Resources/Sprites/Enemies/moto.gif b/Knuckle's Adventure/Resources/Sprites/Enemies/moto.gif
new file mode 100644
index 0000000..dd0d9ad
Binary files /dev/null and b/Knuckle's Adventure/Resources/Sprites/Enemies/moto.gif differ
diff --git a/Knuckle's Adventure/Resources/Sprites/Player/fireball.gif b/Knuckle's Adventure/Resources/Sprites/Player/fireball.gif
new file mode 100644
index 0000000..b490d13
Binary files /dev/null and b/Knuckle's Adventure/Resources/Sprites/Player/fireball.gif differ
diff --git a/Knuckle's Adventure/Resources/Sprites/Player/knucks.gif b/Knuckle's Adventure/Resources/Sprites/Player/knucks.gif
new file mode 100644
index 0000000..2df54df
Binary files /dev/null and b/Knuckle's Adventure/Resources/Sprites/Player/knucks.gif differ
diff --git a/Knuckle's Adventure/Resources/Sprites/Player/rings ss.gif b/Knuckle's Adventure/Resources/Sprites/Player/rings ss.gif
new file mode 100644
index 0000000..b4fd65d
Binary files /dev/null and b/Knuckle's Adventure/Resources/Sprites/Player/rings ss.gif differ
diff --git a/Knuckle's Adventure/Resources/Tilesets/Thumbs.db b/Knuckle's Adventure/Resources/Tilesets/Thumbs.db
new file mode 100644
index 0000000..508ec66
Binary files /dev/null and b/Knuckle's Adventure/Resources/Tilesets/Thumbs.db differ
diff --git a/Knuckle's Adventure/Resources/Tilesets/TileSet.gif b/Knuckle's Adventure/Resources/Tilesets/TileSet.gif
new file mode 100644
index 0000000..fc2ef33
Binary files /dev/null and b/Knuckle's Adventure/Resources/Tilesets/TileSet.gif differ
diff --git a/Knuckle's Adventure/Resources/Tilesets/grasstileset.gif b/Knuckle's Adventure/Resources/Tilesets/grasstileset.gif
new file mode 100644
index 0000000..f53b848
Binary files /dev/null and b/Knuckle's Adventure/Resources/Tilesets/grasstileset.gif differ
diff --git a/Knuckle's Adventure/src/Audio/AudioPlayer.java b/Knuckle's Adventure/src/Audio/AudioPlayer.java
new file mode 100644
index 0000000..a01f93f
--- /dev/null
+++ b/Knuckle's Adventure/src/Audio/AudioPlayer.java
@@ -0,0 +1,71 @@
+package Audio;
+
+import javax.sound.sampled.*;
+
+public class AudioPlayer {
+
+ private Clip clip;
+
+ public AudioPlayer(String s) {
+
+ try {
+
+ AudioInputStream ais =
+ AudioSystem.getAudioInputStream(
+ getClass().getResourceAsStream(
+ s
+ )
+ );
+ AudioFormat baseFormat = ais.getFormat();
+ AudioFormat decodeFormat = new AudioFormat(
+ AudioFormat.Encoding.PCM_SIGNED,
+ baseFormat.getSampleRate(),
+ 16,
+ baseFormat.getChannels(),
+ baseFormat.getChannels() * 2,
+ baseFormat.getSampleRate(),
+ false
+ );
+ AudioInputStream dais =
+ AudioSystem.getAudioInputStream(
+ decodeFormat, ais);
+ clip = AudioSystem.getClip();
+ clip.open(dais);
+ }
+ catch(Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ public void play() {
+ if(clip == null) return;
+ stop();
+ clip.setFramePosition(0);
+ clip.start();
+ }
+
+ public void stop() {
+ if(clip.isRunning()) clip.stop();
+ }
+
+ public void close() {
+ stop();
+ clip.close();
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Knuckle's Adventure/src/Entity/Animation.java b/Knuckle's Adventure/src/Entity/Animation.java
new file mode 100644
index 0000000..32ef387
--- /dev/null
+++ b/Knuckle's Adventure/src/Entity/Animation.java
@@ -0,0 +1,65 @@
+package Entity;
+
+import java.awt.image.BufferedImage;
+
+public class Animation {
+
+ private BufferedImage[] frames;
+ private int currentFrame;
+
+ private long startTime;
+ private long delay;
+
+ private boolean playedOnce;
+
+ public Animation() {
+ playedOnce = false;
+ }
+
+ public void setFrames(BufferedImage[] frames) {
+ this.frames = frames;
+ currentFrame = 0;
+ startTime = System.nanoTime();
+ playedOnce = false;
+ }
+
+ public void setDelay(long d) { delay = d; }
+ public void setFrame(int i) { currentFrame = i; }
+
+ public void update() {
+
+ if(delay == -1) return;
+
+ long elapsed = (System.nanoTime() - startTime) / 1000000;
+ if(elapsed > delay) {
+ currentFrame++;
+ startTime = System.nanoTime();
+ }
+ if(currentFrame == frames.length) {
+ currentFrame = 0;
+ playedOnce = true;
+ }
+
+ }
+
+ public int getFrame() { return currentFrame; }
+ public BufferedImage getImage() { return frames[currentFrame]; }
+ public boolean hasPlayedOnce() { return playedOnce; }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Knuckle's Adventure/src/Entity/Blast.java b/Knuckle's Adventure/src/Entity/Blast.java
new file mode 100644
index 0000000..4464551
--- /dev/null
+++ b/Knuckle's Adventure/src/Entity/Blast.java
@@ -0,0 +1,123 @@
+package Entity;
+
+import TileMap.TileMap;
+
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import javax.imageio.ImageIO;
+
+public class Blast extends MapObject {
+
+ private boolean hit;
+ private boolean remove;
+ private BufferedImage[] sprites;
+ private BufferedImage[] hitSprites;
+
+ public Blast(TileMap tm, boolean right) {
+
+ super(tm);
+
+ facingRight = right;
+
+ moveSpeed = 3.8;
+ if(right) dx = moveSpeed;
+ else dx = -moveSpeed;
+
+ width = 16;
+ height = 16;
+ cwidth = 14;
+ cheight = 14;
+
+ // load sprites
+ try {
+
+ BufferedImage spritesheet = ImageIO.read(
+ getClass().getResourceAsStream(
+ "/Sprites/Player/rings ss.gif"
+ )
+ );
+
+ sprites = new BufferedImage[8];
+ for(int i = 0; i < sprites.length; i++) {
+ sprites[i] = spritesheet.getSubimage(
+ i * width,
+ 0,
+ width,
+ height
+ );
+ }
+
+ hitSprites = new BufferedImage[7];
+ for(int i = 0; i < hitSprites.length; i++) {
+ hitSprites[i] = spritesheet.getSubimage(
+ i * width,
+ height,
+ width,
+ height
+ );
+ }
+
+ animation = new Animation();
+ animation.setFrames(sprites);
+ animation.setDelay(70);
+
+ }
+ catch(Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ public void setHit() {
+ if(hit) return;
+ hit = true;
+ animation.setFrames(hitSprites);
+ animation.setDelay(70);
+ dx = 0;
+ }
+
+ public boolean shouldRemove() { return remove; }
+
+ public void update() {
+
+ checkTileMapCollision();
+ setPosition(xtemp, ytemp);
+
+ if(dx == 0 && !hit) {
+ setHit();
+ }
+
+ animation.update();
+ if(hit && animation.hasPlayedOnce()) {
+ remove = true;
+ }
+
+ }
+
+ public void draw(Graphics2D g) {
+
+ setMapPosition();
+
+ super.draw(g);
+
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Knuckle's Adventure/src/Entity/Enemies/Motobug.java b/Knuckle's Adventure/src/Entity/Enemies/Motobug.java
new file mode 100644
index 0000000..35ce67e
--- /dev/null
+++ b/Knuckle's Adventure/src/Entity/Enemies/Motobug.java
@@ -0,0 +1,142 @@
+package Entity.Enemies;
+
+import Entity.*;
+import TileMap.TileMap;
+
+import java.awt.image.BufferedImage;
+import java.awt.Graphics2D;
+
+import javax.imageio.ImageIO;
+
+public class Motobug extends Enemy {
+
+ private BufferedImage[] sprites;
+
+ public Motobug(TileMap tm) {
+
+ super(tm);
+
+ moveSpeed = 0.3;
+ maxSpeed = 0.3;
+ fallSpeed = 0.2;
+ maxFallSpeed = 10.0;
+
+ width = 48;
+ height = 48;
+ cwidth = 45;
+ cheight = 45;
+
+ health = maxHealth = 2;
+ damage = 1;
+
+ // load sprites
+ try {
+
+ BufferedImage spritesheet = ImageIO.read(
+ getClass().getResourceAsStream(
+ "/Sprites/Enemies/moto.gif"
+ )
+ );
+
+ sprites = new BufferedImage[3];
+ for(int i = 0; i < sprites.length; i++) {
+ sprites[i] = spritesheet.getSubimage(
+ i * width,
+ 0,
+ width,
+ height
+ );
+ }
+
+ }
+ catch(Exception e) {
+ e.printStackTrace();
+ }
+
+ animation = new Animation();
+ animation.setFrames(sprites);
+ animation.setDelay(300);
+
+ right = true;
+ facingRight = true;
+
+ }
+
+ private void getNextPosition() {
+
+ // movement
+ if(left) {
+ dx -= moveSpeed;
+ if(dx < -maxSpeed) {
+ dx = -maxSpeed;
+ }
+ }
+ else if(right) {
+ dx += moveSpeed;
+ if(dx > maxSpeed) {
+ dx = maxSpeed;
+ }
+ }
+
+ // falling
+ if(falling) {
+ dy += fallSpeed;
+ }
+
+ }
+
+ public void update() {
+
+ // update position
+ getNextPosition();
+ checkTileMapCollision();
+ setPosition(xtemp, ytemp);
+
+ // check flinching
+ if(flinching) {
+ long elapsed =
+ (System.nanoTime() - flinchTimer) / 1000000;
+ if(elapsed > 400) {
+ flinching = false;
+ }
+ }
+
+ // if it hits a wall, go other direction
+ if(right && dx == 0) {
+ right = false;
+ left = true;
+ facingRight = false;
+ }
+ else if(left && dx == 0) {
+ right = true;
+ left = false;
+ facingRight = true;
+ }
+
+ // update animation
+ animation.update();
+
+ }
+
+ public void draw(Graphics2D g) {
+
+ //if(notOnScreen()) return;
+
+ setMapPosition();
+
+ super.draw(g);
+
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Knuckle's Adventure/src/Entity/Enemy.java b/Knuckle's Adventure/src/Entity/Enemy.java
new file mode 100644
index 0000000..fce4459
--- /dev/null
+++ b/Knuckle's Adventure/src/Entity/Enemy.java
@@ -0,0 +1,48 @@
+package Entity;
+
+import TileMap.TileMap;
+
+public class Enemy extends MapObject {
+
+ protected int health;
+ protected int maxHealth;
+ protected boolean dead;
+ protected int damage;
+
+ protected boolean flinching;
+ protected long flinchTimer;
+
+ public Enemy(TileMap tm) {
+ super(tm);
+ }
+
+ public boolean isDead() { return dead; }
+
+ public int getDamage() { return damage; }
+
+ public void hit(int damage) {
+ if(dead || flinching) return;
+ health -= damage;
+ if(health < 0) health = 0;
+ if(health == 0) dead = true;
+ flinching = true;
+ flinchTimer = System.nanoTime();
+ }
+
+ public void update() {}
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Knuckle's Adventure/src/Entity/Explosion.java b/Knuckle's Adventure/src/Entity/Explosion.java
new file mode 100644
index 0000000..97dcb47
--- /dev/null
+++ b/Knuckle's Adventure/src/Entity/Explosion.java
@@ -0,0 +1,99 @@
+package Entity;
+
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import javax.imageio.ImageIO;
+
+public class Explosion {
+
+ private int x;
+ private int y;
+ private int xmap;
+ private int ymap;
+
+ private int width;
+ private int height;
+
+ private Animation animation;
+ private BufferedImage[] sprites;
+
+ private boolean remove;
+
+ public Explosion(int x, int y) {
+
+ this.x = x;
+ this.y = y;
+
+ width = 30;
+ height = 30;
+
+ try {
+
+ BufferedImage spritesheet = ImageIO.read(
+ getClass().getResourceAsStream(
+ "/Sprites/Enemies/explosion.gif"
+ )
+ );
+
+ sprites = new BufferedImage[6];
+ for(int i = 0; i < sprites.length; i++) {
+ sprites[i] = spritesheet.getSubimage(
+ i * width,
+ 0,
+ width,
+ height
+ );
+ }
+
+ }
+ catch(Exception e) {
+ e.printStackTrace();
+ }
+
+ animation = new Animation();
+ animation.setFrames(sprites);
+ animation.setDelay(70);
+
+ }
+
+ public void update() {
+ animation.update();
+ if(animation.hasPlayedOnce()) {
+ remove = true;
+ }
+ }
+
+ public boolean shouldRemove() { return remove; }
+
+ public void setMapPosition(int x, int y) {
+ xmap = x;
+ ymap = y;
+ }
+
+ public void draw(Graphics2D g) {
+ g.drawImage(
+ animation.getImage(),
+ x + xmap - width / 2,
+ y + ymap - height / 2,
+ null
+ );
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Knuckle's Adventure/src/Entity/HUD.java b/Knuckle's Adventure/src/Entity/HUD.java
new file mode 100644
index 0000000..5d144ea
--- /dev/null
+++ b/Knuckle's Adventure/src/Entity/HUD.java
@@ -0,0 +1,58 @@
+package Entity;
+
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import javax.imageio.ImageIO;
+
+public class HUD {
+
+ private Knuckles knuckles;
+
+ private BufferedImage image;
+ private Font font;
+
+ public HUD(Knuckles p) {
+ knuckles = p;
+ try {
+ image = ImageIO.read(
+ getClass().getResourceAsStream(
+ "/HUD/hud.gif"
+ )
+ );
+ font = new Font("Arial", Font.PLAIN, 14);
+ }
+ catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+ public void update() {
+
+ }
+
+ public void draw(Graphics2D g) {
+
+ g.drawImage(image, 0, 10, null);
+ g.setFont(font);
+ g.setColor(Color.WHITE);
+ g.drawString(
+ knuckles.getHealth() + "/" + knuckles.getMaxHealth(),
+ 55,
+ 45
+ );
+
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Knuckle's Adventure/src/Entity/Knuckles.java b/Knuckle's Adventure/src/Entity/Knuckles.java
new file mode 100644
index 0000000..d0b6aa0
--- /dev/null
+++ b/Knuckle's Adventure/src/Entity/Knuckles.java
@@ -0,0 +1,431 @@
+package Entity;
+
+import TileMap.*;
+import Audio.AudioPlayer;
+
+import java.util.ArrayList;
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.util.HashMap;
+
+public class Knuckles extends MapObject {
+
+ // player stuff
+ private int health;
+ private int maxHealth;
+ private int fire;
+ private int maxFire;
+ private boolean dead;
+ private boolean flinching;
+ private long flinchTimer;
+
+ // blast
+ private boolean firing;
+ private int fireCost;
+ private int fireBallDamage;
+ private ArrayList blasts;
+
+ // punch
+ private boolean punching;
+ private int punchDamage;
+ private int punchRange;
+
+ // gliding
+ private boolean gliding;
+
+ // animations
+ private ArrayList sprites;
+ private final int[] numFrames = {
+ 7, 8, 1, 3, 1, 2,
+ };
+
+ // animation actions
+ private static final int IDLE = 0;
+ private static final int WALKING = 1;
+ private static final int JUMPING = 2;
+ private static final int FALLING = 3;
+ private static final int GLIDING = 4;
+ private static final int BLAST = 5;
+ private static final int PUNCHING = 6;
+
+ private HashMap sfx;
+
+ public Knuckles(TileMap tm) {
+
+ super(tm);
+
+ width = 96;
+ height = 96;
+ cwidth = 80;
+ cheight = 80;
+
+ moveSpeed = 4.0;
+ maxSpeed = 7.6;
+ stopSpeed = 0.4;
+ fallSpeed = .15;
+ maxFallSpeed = 6.0;
+ jumpStart = -7.8;
+ stopJumpSpeed = 0.3;
+
+ facingRight = true;
+
+ health = maxHealth = 5;
+ fire = maxFire = 2500;
+
+ fireCost = 200;
+ fireBallDamage = 5;
+ blasts = new ArrayList();
+
+ punchDamage = 8;
+ punchRange = 40;
+
+ // load sprites
+ try {
+
+ BufferedImage spritesheet = ImageIO.read(
+ getClass().getResourceAsStream(
+ "/Sprites/Player/knucks.gif"
+ )
+ );
+
+ sprites = new ArrayList();
+ for(int i = 0; i < 9; i++) {
+
+ BufferedImage[] bi =
+ new BufferedImage[numFrames[i]];
+
+ for(int j = 0; j < numFrames[i]; j++) {
+
+ if(i != PUNCHING) {
+ bi[j] = spritesheet.getSubimage(
+ j * width,
+ i * height,
+ width,
+ height
+ );
+ }
+ else {
+ bi[j] = spritesheet.getSubimage(
+ j * width * 2,
+ i * height,
+ width * 2,
+ height
+ );
+ }
+
+ }
+
+ sprites.add(bi);
+
+ }
+
+ }
+ catch(Exception e) {
+ e.printStackTrace();
+ }
+
+ animation = new Animation();
+ currentAction = IDLE;
+ animation.setFrames(sprites.get(IDLE));
+ animation.setDelay(400);
+
+ sfx = new HashMap();
+ sfx.put("jump", new AudioPlayer("/SFX/jump.mp3"));
+ sfx.put("scratch", new AudioPlayer("/SFX/punch.mp3"));
+
+ }
+
+ public int getHealth() { return health; }
+ public int getMaxHealth() { return maxHealth; }
+ public int getFire() { return fire; }
+ public int getMaxFire() { return maxFire; }
+
+ public void setFiring() {
+ firing = true;
+ }
+ public void setScratching() {
+ punching = true;
+ }
+ public void setGliding(boolean b) {
+ gliding = b;
+ }
+
+ public void checkAttack(ArrayList enemies) {
+
+ // loop through enemies
+ for(int i = 0; i < enemies.size(); i++) {
+
+ Enemy e = enemies.get(i);
+
+ // scratch attack
+ if(punching) {
+ if(facingRight) {
+ if(
+ e.getx() > x &&
+ e.getx() < x + punchRange &&
+ e.gety() > y - height / 2 &&
+ e.gety() < y + height / 2
+ ) {
+ e.hit(punchDamage);
+ }
+ }
+ else {
+ if(
+ e.getx() < x &&
+ e.getx() > x - punchRange &&
+ e.gety() > y - height / 2 &&
+ e.gety() < y + height / 2
+ ) {
+ e.hit(punchDamage);
+ }
+ }
+ }
+
+ // blasts
+ for(int j = 0; j < blasts.size(); j++) {
+ if(blasts.get(j).intersects(e)) {
+ e.hit(fireBallDamage);
+ blasts.get(j).setHit();
+ break;
+ }
+ }
+
+ // check enemy collision
+ if(intersects(e)) {
+ hit(e.getDamage());
+ }
+
+ }
+
+ }
+
+ public void hit(int damage) {
+ if(flinching) return;
+ health -= damage;
+ if(health < 0) health = 0;
+ if(health == 0) dead = true;
+ flinching = true;
+ flinchTimer = System.nanoTime();
+ }
+
+ private void getNextPosition() {
+
+ // movement
+ if(left) {
+ dx -= moveSpeed;
+ if(dx < -maxSpeed) {
+ dx = -maxSpeed;
+ }
+ }
+ else if(right) {
+ dx += moveSpeed;
+ if(dx > maxSpeed) {
+ dx = maxSpeed;
+ }
+ }
+ else {
+ if(dx > 0) {
+ dx -= stopSpeed;
+ if(dx < 0) {
+ dx = 0;
+ }
+ }
+ else if(dx < 0) {
+ dx += stopSpeed;
+ if(dx > 0) {
+ dx = 0;
+ }
+ }
+ }
+
+ // cannot move while attacking, except in air
+ if(
+ (currentAction == PUNCHING || currentAction == BLAST) &&
+ !(jumping || falling)) {
+ dx = 0;
+ }
+
+ // jumping
+ if(jumping && !falling) {
+ sfx.get("jump").play();
+ dy = jumpStart;
+ falling = true;
+ }
+
+ // falling
+ if(falling) {
+
+ if(dy > 0 && gliding) dy += fallSpeed * 0.1;
+ else dy += fallSpeed;
+
+ if(dy > 0) jumping = false;
+ if(dy < 0 && !jumping) dy += stopJumpSpeed;
+
+ if(dy > maxFallSpeed) dy = maxFallSpeed;
+
+ }
+
+ }
+
+ public boolean isDead(){
+ if (this.getHealth() == 0){
+ return true;
+ }
+ return false;
+ }
+
+ public void update() {
+
+ // update position
+ getNextPosition();
+ checkTileMapCollision();
+ setPosition(xtemp, ytemp);
+
+ // check attack has stopped
+ if(currentAction == PUNCHING) {
+ if(animation.hasPlayedOnce()) punching = false;
+ }
+ if(currentAction == BLAST) {
+ if(animation.hasPlayedOnce()) firing = false;
+ }
+
+ // blast attack
+ fire += 1;
+ if(fire > maxFire) fire = maxFire;
+ if(firing && currentAction != BLAST) {
+ if(fire > fireCost) {
+ fire -= fireCost;
+ Blast fb = new Blast(tileMap, facingRight);
+ fb.setPosition(x, y);
+ blasts.add(fb);
+ }
+ }
+
+ // update blasts
+ for(int i = 0; i < blasts.size(); i++) {
+ blasts.get(i).update();
+ if(blasts.get(i).shouldRemove()) {
+ blasts.remove(i);
+ i--;
+ }
+ }
+
+ // check done flinching
+ if(flinching) {
+ long elapsed =
+ (System.nanoTime() - flinchTimer) / 1000000;
+ if(elapsed > 1000) {
+ flinching = false;
+ }
+ }
+
+ // set animation
+ if(punching) {
+ if(currentAction != PUNCHING) {
+ sfx.get("scratch").play();
+ currentAction = PUNCHING;
+ animation.setFrames(sprites.get(PUNCHING));
+ animation.setDelay(50);
+ width = 60;
+ }
+ }
+ else if(firing) {
+ if(currentAction != BLAST) {
+ currentAction = BLAST;
+ animation.setFrames(sprites.get(BLAST));
+ animation.setDelay(100);
+ width = 30;
+ }
+ }
+ else if(dy > 0) {
+ if(gliding) {
+ if(currentAction != GLIDING) {
+ currentAction = GLIDING;
+ animation.setFrames(sprites.get(GLIDING));
+ animation.setDelay(100);
+ width = 30;
+ }
+ }
+ else if(currentAction != FALLING) {
+ currentAction = FALLING;
+ animation.setFrames(sprites.get(FALLING));
+ animation.setDelay(100);
+ width = 30;
+ }
+ }
+ else if(dy < 0) {
+ if(currentAction != JUMPING) {
+ currentAction = JUMPING;
+ animation.setFrames(sprites.get(JUMPING));
+ animation.setDelay(-1);
+ width = 30;
+ }
+ }
+ else if(left || right) {
+ if(currentAction != WALKING) {
+ currentAction = WALKING;
+ animation.setFrames(sprites.get(WALKING));
+ animation.setDelay(40);
+ width = 30;
+ }
+ }
+ else {
+ if(currentAction != IDLE) {
+ currentAction = IDLE;
+ animation.setFrames(sprites.get(IDLE));
+ animation.setDelay(400);
+ width = 30;
+ }
+ }
+
+ animation.update();
+
+ // set direction
+ if(currentAction != PUNCHING && currentAction != BLAST) {
+ if(right) facingRight = true;
+ if(left) facingRight = false;
+ }
+
+ }
+
+ public void draw(Graphics2D g) {
+
+ setMapPosition();
+
+ // draw blasts
+ for(int i = 0; i < blasts.size(); i++) {
+ blasts.get(i).draw(g);
+ }
+
+ // draw player
+ if(flinching) {
+ long elapsed =
+ (System.nanoTime() - flinchTimer) / 1000000;
+ if(elapsed / 100 % 2 == 0) {
+ return;
+ }
+ }
+
+ super.draw(g);
+
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Knuckle's Adventure/src/Entity/MapObject.java b/Knuckle's Adventure/src/Entity/MapObject.java
new file mode 100644
index 0000000..da36f07
--- /dev/null
+++ b/Knuckle's Adventure/src/Entity/MapObject.java
@@ -0,0 +1,238 @@
+package Entity;
+
+import Main.GamePanel;
+import TileMap.TileMap;
+import TileMap.Tile;
+
+import java.awt.Rectangle;
+
+public abstract class MapObject {
+
+ // tile stuff
+ protected TileMap tileMap;
+ protected int tileSize;
+ protected double xmap;
+ protected double ymap;
+
+ // position and vector
+ protected double x;
+ protected double y;
+ protected double dx;
+ protected double dy;
+
+ // dimensions
+ protected int width;
+ protected int height;
+
+ // collision box
+ protected int cwidth;
+ protected int cheight;
+
+ // collision
+ protected int currRow;
+ protected int currCol;
+ protected double xdest;
+ protected double ydest;
+ protected double xtemp;
+ protected double ytemp;
+ protected boolean topLeft;
+ protected boolean topRight;
+ protected boolean bottomLeft;
+ protected boolean bottomRight;
+
+ // animation
+ protected Animation animation;
+ protected int currentAction;
+ protected int previousAction;
+ protected boolean facingRight;
+
+ // movement
+ protected boolean left;
+ protected boolean right;
+ protected boolean up;
+ protected boolean down;
+ protected boolean jumping;
+ protected boolean falling;
+
+ // movement attributes
+ protected double moveSpeed;
+ protected double maxSpeed;
+ protected double stopSpeed;
+ protected double fallSpeed;
+ protected double maxFallSpeed;
+ protected double jumpStart;
+ protected double stopJumpSpeed;
+
+ // constructor
+ public MapObject(TileMap tm) {
+ tileMap = tm;
+ tileSize = tm.getTileSize();
+ }
+
+ public boolean intersects(MapObject o) {
+ Rectangle r1 = getRectangle();
+ Rectangle r2 = o.getRectangle();
+ return r1.intersects(r2);
+ }
+
+ public Rectangle getRectangle() {
+ return new Rectangle(
+ (int)x - cwidth,
+ (int)y - cheight,
+ cwidth,
+ cheight
+ );
+ }
+
+ public void calculateCorners(double x, double y) {
+
+ int leftTile = (int)(x - cwidth / 2) / tileSize;
+ int rightTile = (int)(x + cwidth / 2 - 1) / tileSize;
+ int topTile = (int)(y - cheight / 2) / tileSize;
+ int bottomTile = (int)(y + cheight / 2 - 1) / tileSize;
+
+ int tl = tileMap.getType(topTile, leftTile);
+ int tr = tileMap.getType(topTile, rightTile);
+ int bl = tileMap.getType(bottomTile, leftTile);
+ int br = tileMap.getType(bottomTile, rightTile);
+
+ topLeft = tl == Tile.BLOCKED;
+ topRight = tr == Tile.BLOCKED;
+ bottomLeft = bl == Tile.BLOCKED;
+ bottomRight = br == Tile.BLOCKED;
+
+ }
+
+ public void checkTileMapCollision() {
+
+ currCol = (int)x / tileSize;
+ currRow = (int)y / tileSize;
+
+ xdest = x + dx;
+ ydest = y + dy;
+
+ xtemp = x;
+ ytemp = y;
+
+ calculateCorners(x, ydest);
+ if(dy < 0) {
+ if(topLeft || topRight) {
+ dy = 0;
+ ytemp = currRow * tileSize + cheight / 2;
+ }
+ else {
+ ytemp += dy;
+ }
+ }
+ if(dy > 0) {
+ if(bottomLeft || bottomRight) {
+ dy = 0;
+ falling = false;
+ ytemp = (currRow + 1) * tileSize - cheight / 2;
+ }
+ else {
+ ytemp += dy;
+ }
+ }
+
+ calculateCorners(xdest, y);
+ if(dx < 0) {
+ if(topLeft || bottomLeft) {
+ dx = 0;
+ xtemp = currCol * tileSize + cwidth / 2;
+ }
+ else {
+ xtemp += dx;
+ }
+ }
+ if(dx > 0) {
+ if(topRight || bottomRight) {
+ dx = 0;
+ xtemp = (currCol + 1) * tileSize - cwidth / 2;
+ }
+ else {
+ xtemp += dx;
+ }
+ }
+
+ if(!falling) {
+ calculateCorners(x, ydest + 1);
+ if(!bottomLeft && !bottomRight) {
+ falling = true;
+ }
+ }
+
+ }
+
+ public int getx() { return (int)x; }
+ public int gety() { return (int)y; }
+ public int getWidth() { return width; }
+ public int getHeight() { return height; }
+ public int getCWidth() { return cwidth; }
+ public int getCHeight() { return cheight; }
+
+ public void setPosition(double x, double y) {
+ this.x = x;
+ this.y = y;
+ }
+ public void setVector(double dx, double dy) {
+ this.dx = dx;
+ this.dy = dy;
+ }
+
+ public void setMapPosition() {
+ xmap = tileMap.getx();
+ ymap = tileMap.gety();
+ }
+
+ public void setLeft(boolean b) { left = b; }
+ public void setRight(boolean b) { right = b; }
+ public void setUp(boolean b) { up = b; }
+ public void setDown(boolean b) { down = b; }
+ public void setJumping(boolean b) { jumping = b; }
+
+ public boolean notOnScreen() {
+ return x + xmap + width < 0 ||
+ x + xmap - width > GamePanel.WIDTH ||
+ y + ymap + height < 0 ||
+ y + ymap - height > GamePanel.HEIGHT;
+ }
+
+ public void draw(java.awt.Graphics2D g) {
+ if(facingRight) {
+ g.drawImage(
+ animation.getImage(),
+ (int)(x + xmap - width / 2),
+ (int)(y + ymap - height / 2),
+ null
+ );
+ }
+ else {
+ g.drawImage(
+ animation.getImage(),
+ (int)(x + xmap - width / 2 + 2*width),
+ (int)(y + ymap - height / 2),
+ -3*width,
+ height,
+ null
+ );
+ }
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Knuckle's Adventure/src/GameState/GameState.java b/Knuckle's Adventure/src/GameState/GameState.java
new file mode 100644
index 0000000..5af1653
--- /dev/null
+++ b/Knuckle's Adventure/src/GameState/GameState.java
@@ -0,0 +1,13 @@
+package GameState;
+
+public abstract class GameState {
+
+ protected GameStateManager gsm;
+
+ public abstract void init();
+ public abstract void update();
+ public abstract void draw(java.awt.Graphics2D g);
+ public abstract void keyPressed(int k);
+ public abstract void keyReleased(int k);
+
+}
diff --git a/Knuckle's Adventure/src/GameState/GameStateManager.java b/Knuckle's Adventure/src/GameState/GameStateManager.java
new file mode 100644
index 0000000..80b2a9a
--- /dev/null
+++ b/Knuckle's Adventure/src/GameState/GameStateManager.java
@@ -0,0 +1,70 @@
+package GameState;
+
+import java.util.ArrayList;
+
+public class GameStateManager {
+
+ private GameState[] gameStates;
+ private int currentState;
+
+ public static final int NUMGAMESTATES = 2;
+ public static final int MENUSTATE = 0;
+ public static final int LEVEL1STATE = 1;
+
+ public GameStateManager() {
+
+ gameStates = new GameState[NUMGAMESTATES];
+
+ currentState = MENUSTATE;
+ loadState(currentState);
+
+ }
+
+ void loadState(int state) {
+ if(state == MENUSTATE)
+ gameStates[state] = new MenuState(this);
+ if(state == LEVEL1STATE)
+ gameStates[state] = new Level1State(this);
+ }
+
+ private void unloadState(int state) {
+ gameStates[state] = null;
+ }
+
+ public void setState(int state) {
+ unloadState(currentState);
+ currentState = state;
+ loadState(currentState);
+ //gameStates[currentState].init();
+ }
+
+ public void update() {
+ try {
+ gameStates[currentState].update();
+ } catch(Exception e) {}
+ }
+
+ public void draw(java.awt.Graphics2D g) {
+ try {
+ gameStates[currentState].draw(g);
+ } catch(Exception e) {}
+ }
+
+ public void keyPressed(int k) {
+ gameStates[currentState].keyPressed(k);
+ }
+
+ public void keyReleased(int k) {
+ gameStates[currentState].keyReleased(k);
+ }
+
+}
+
+
+
+
+
+
+
+
+
diff --git a/Knuckle's Adventure/src/GameState/Level1State.java b/Knuckle's Adventure/src/GameState/Level1State.java
new file mode 100644
index 0000000..5a1a2b1
--- /dev/null
+++ b/Knuckle's Adventure/src/GameState/Level1State.java
@@ -0,0 +1,182 @@
+package GameState;
+
+import Main.GamePanel;
+import TileMap.*;
+import Entity.*;
+import Entity.Enemies.*;
+import Audio.AudioPlayer;
+import Main.Game;
+
+import javax.swing.JFrame;
+
+import com.sun.java.swing.plaf.windows.resources.windows;
+
+import java.awt.*;
+import java.awt.event.KeyEvent;
+import java.util.ArrayList;
+
+
+
+public class Level1State extends GameState {
+
+ private TileMap tileMap;
+ private Background bg;
+
+ private Knuckles knuckles;
+
+ private ArrayList enemies;
+ private ArrayList explosions;
+
+ private HUD hud;
+
+ private AudioPlayer bgMusic;
+
+ public Level1State(GameStateManager gsm) {
+ this.gsm = gsm;
+ init();
+ }
+
+ public void init() {
+
+ tileMap = new TileMap(96);
+ tileMap.loadTiles("/Tilesets/TileSet.gif");
+ tileMap.loadMap("/Maps/level1-1.map");
+ tileMap.setPosition(0, 0);
+ tileMap.setTween(1);
+
+ bg = new Background("/Backgrounds/SunSetHill1.gif", 0.0);
+
+ knuckles = new Knuckles(tileMap);
+ knuckles.setPosition(140, 300);
+
+ populateEnemies();
+
+ explosions = new ArrayList();
+
+ hud = new HUD(knuckles);
+
+ bgMusic = new AudioPlayer("/Music/Tee.mp3");
+ bgMusic.play();
+
+ }
+
+ private void populateEnemies() {
+
+ enemies = new ArrayList();
+
+ Motobug m;
+ Point[] points = new Point[] {
+ new Point(200, 100),
+ new Point(860, 200),
+ new Point(2496, 200),
+ new Point(3168, 200),
+ new Point(3744, 200),
+ new Point(4608, 350)
+ };
+ for(int i = 0; i < points.length; i++) {
+ m = new Motobug(tileMap);
+ m.setPosition(points[i].x, points[i].y);
+ enemies.add(m);
+ }
+
+ }
+
+ public void update() {
+
+ // update player
+ knuckles.update();
+ tileMap.setPosition(
+ GamePanel.WIDTH / 2 - knuckles.getx(),
+ GamePanel.HEIGHT / 2 - knuckles.gety()
+ );
+
+ // set background
+ bg.setPosition(tileMap.getx(), tileMap.gety());
+
+ // attack enemies
+ knuckles.checkAttack(enemies);
+
+ // update all enemies
+ for(int i = 0; i < enemies.size(); i++) {
+ Enemy e = enemies.get(i);
+ e.update();
+ if(e.isDead()) {
+ enemies.remove(i);
+ i--;
+ explosions.add(
+ new Explosion(e.getx(), e.gety()));
+ }
+ }
+
+ // update explosions
+ for(int i = 0; i < explosions.size(); i++) {
+ explosions.get(i).update();
+ if(explosions.get(i).shouldRemove()) {
+ explosions.remove(i);
+ i--;
+ }
+ }
+
+ }
+
+ public void draw(Graphics2D g) {
+
+ // draw bg
+ bg.draw(g);
+
+ // draw tilemap
+ tileMap.draw(g);
+
+ // draw player
+ knuckles.draw(g);
+
+ // draw enemies
+ for(int i = 0; i < enemies.size(); i++) {
+ enemies.get(i).draw(g);
+ }
+
+ // draw explosions
+ for(int i = 0; i < explosions.size(); i++) {
+ explosions.get(i).setMapPosition(
+ (int)tileMap.getx(), (int)tileMap.gety());
+ explosions.get(i).draw(g);
+ }
+
+ // draw hud
+ hud.draw(g);
+
+ }
+
+ public void keyPressed(int k) {
+ if(k == KeyEvent.VK_LEFT) knuckles.setLeft(true);
+ if(k == KeyEvent.VK_RIGHT) knuckles.setRight(true);
+ if(k == KeyEvent.VK_UP) knuckles.setUp(true);
+ if(k == KeyEvent.VK_DOWN) knuckles.setDown(true);
+ if(k == KeyEvent.VK_W) knuckles.setJumping(true);
+ if(k == KeyEvent.VK_E) knuckles.setGliding(true);
+ if(k == KeyEvent.VK_R) knuckles.setScratching();
+ if(k == KeyEvent.VK_F) knuckles.setFiring();
+ }
+
+ public void keyReleased(int k) {
+ if(k == KeyEvent.VK_LEFT) knuckles.setLeft(false);
+ if(k == KeyEvent.VK_RIGHT) knuckles.setRight(false);
+ if(k == KeyEvent.VK_UP) knuckles.setUp(false);
+ if(k == KeyEvent.VK_DOWN) knuckles.setDown(false);
+ if(k == KeyEvent.VK_W) knuckles.setJumping(false);
+ if(k == KeyEvent.VK_E) knuckles.setGliding(false);
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Knuckle's Adventure/src/GameState/MenuState.java b/Knuckle's Adventure/src/GameState/MenuState.java
new file mode 100644
index 0000000..1748f56
--- /dev/null
+++ b/Knuckle's Adventure/src/GameState/MenuState.java
@@ -0,0 +1,77 @@
+package GameState;
+
+import Audio.AudioPlayer;
+import TileMap.Background;
+
+import java.awt.*;
+import java.awt.event.KeyEvent;
+import java.awt.image.BufferedImage;
+
+import javax.imageio.ImageIO;
+
+public class MenuState extends GameState {
+
+ private Background bg;
+ private BufferedImage icon;
+
+ private Font font;
+ private AudioPlayer bgMusic;
+
+ public MenuState(GameStateManager gsm) {
+
+ this.gsm = gsm;
+
+try {
+
+ //Loads Background
+ bg = new Background("/Menu/Island_Background2.gif", 1);
+ bg.setVector(-0.125, 0);
+ //Loads Emblem
+ icon = ImageIO.read(getClass().getResourceAsStream("/Menu/Emblem2.gif"));
+ font = new Font("Times New Roman", Font.PLAIN, 13);
+
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+ public void init() {
+
+ bgMusic = new AudioPlayer("/Music/Intro.mp3");
+ bgMusic.play();
+
+ }
+
+ public void update() {
+ bg.update();
+ }
+
+ public void draw(Graphics2D g) {
+
+ // draw bg
+ bg.draw(g);
+ g.drawImage(icon, 0, 0, null);
+
+ g.setFont(font);
+ g.drawString("CSE 2102", 10, 510);
+
+
+ }
+
+ public void keyPressed(int k) {
+ if(k == KeyEvent.VK_ENTER){
+ gsm.setState(GameStateManager.LEVEL1STATE);}
+ }
+
+ public void keyReleased(int k) {}
+
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/Knuckle's Adventure/src/Main/Game.java b/Knuckle's Adventure/src/Main/Game.java
new file mode 100644
index 0000000..7b254a2
--- /dev/null
+++ b/Knuckle's Adventure/src/Main/Game.java
@@ -0,0 +1,18 @@
+package Main;
+
+import javax.swing.JFrame;
+
+public class Game {
+
+ public static void main(String[] args) {
+
+ JFrame window = new JFrame("Knuckle's Adventure");
+ window.setContentPane(new GamePanel());
+ window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ window.setResizable(true);
+ window.pack();
+ window.setVisible(true);
+
+ }
+
+}
diff --git a/Knuckle's Adventure/src/Main/GamePanel.java b/Knuckle's Adventure/src/Main/GamePanel.java
new file mode 100644
index 0000000..ea20b4d
--- /dev/null
+++ b/Knuckle's Adventure/src/Main/GamePanel.java
@@ -0,0 +1,135 @@
+package Main;
+
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.awt.event.*;
+
+import javax.swing.JPanel;
+
+import GameState.GameStateManager;
+
+@SuppressWarnings("serial")
+public class GamePanel extends JPanel
+ implements Runnable, KeyListener{
+
+ // dimensions
+ public static final int WIDTH = 950;
+ public static final int HEIGHT = 520;
+ public static final int SCALE = 2;
+
+ // game thread
+ private Thread thread;
+ private boolean running;
+ private int FPS = 60;
+ private long targetTime = 1000 / FPS;
+
+ // image
+ private BufferedImage image;
+ private Graphics2D g;
+
+ // game state manager
+ private GameStateManager gsm;
+
+ public GamePanel() {
+ super();
+ setPreferredSize(
+ new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
+ setFocusable(true);
+ requestFocus();
+ }
+
+ public void addNotify() {
+ super.addNotify();
+ if(thread == null) {
+ thread = new Thread(this);
+ addKeyListener(this);
+ thread.start();
+ }
+ }
+
+ private void init() {
+
+ image = new BufferedImage(
+ WIDTH, HEIGHT,
+ BufferedImage.TYPE_INT_RGB
+ );
+ g = (Graphics2D) image.getGraphics();
+
+ running = true;
+
+ gsm = new GameStateManager();
+
+ }
+
+ public void run() {
+
+ init();
+
+ long start;
+ long elapsed;
+ long wait;
+
+ // game loop
+ while(running) {
+
+ start = System.nanoTime();
+
+ update();
+ draw();
+ drawToScreen();
+
+ elapsed = System.nanoTime() - start;
+
+ wait = targetTime - elapsed / 1000000;
+ if(wait < 0) wait = 5;
+
+ try {
+ Thread.sleep(wait);
+ }
+ catch(Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ }
+
+ private void update() {
+ gsm.update();
+ }
+ private void draw() {
+ gsm.draw(g);
+ }
+ private void drawToScreen() {
+ Graphics g2 = getGraphics();
+ g2.drawImage(image, 0, 0,
+ WIDTH * SCALE, HEIGHT * SCALE,
+ null);
+ g2.dispose();
+ }
+
+ public void keyTyped(KeyEvent key) {}
+ public void keyPressed(KeyEvent key) {
+ gsm.keyPressed(key.getKeyCode());
+ }
+ public void keyReleased(KeyEvent key) {
+ gsm.keyReleased(key.getKeyCode());
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Knuckle's Adventure/src/TileMap/Background.java b/Knuckle's Adventure/src/TileMap/Background.java
new file mode 100644
index 0000000..9e323e5
--- /dev/null
+++ b/Knuckle's Adventure/src/TileMap/Background.java
@@ -0,0 +1,82 @@
+package TileMap;
+
+import Main.GamePanel;
+
+import java.awt.*;
+import java.awt.image.*;
+import javax.imageio.ImageIO;
+
+public class Background {
+
+ private BufferedImage image;
+
+ private double x;
+ private double y;
+ private double dx;
+ private double dy;
+
+ private double moveScale;
+
+ public Background(String s, double ms) {
+
+ try {
+ image = ImageIO.read(
+ getClass().getResourceAsStream(s)
+ );
+ moveScale = ms;
+ }
+ catch(Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ public void setPosition(double x, double y) {
+ this.x = (x * moveScale) % GamePanel.WIDTH;
+ this.y = (y * moveScale) % GamePanel.HEIGHT;
+ }
+
+ public void setVector(double dx, double dy) {
+ this.dx = dx;
+ this.dy = dy;
+ }
+
+ public void update() {
+ x += dx;
+ y += dy;
+ }
+
+ public void draw(Graphics2D g) {
+
+ g.drawImage(image, (int)x, (int)y, null);
+
+ if(x < 0) {
+ g.drawImage(
+ image,
+
+
+
+
+ (int)x + GamePanel.WIDTH,
+ (int)y,
+ null
+ );
+ }
+ if(x > 0) {
+ g.drawImage(
+ image,
+ (int)x - GamePanel.WIDTH,
+ (int)y,
+ null
+ );
+ }
+ }
+
+}
+
+
+
+
+
+
+
diff --git a/Knuckle's Adventure/src/TileMap/Tile.java b/Knuckle's Adventure/src/TileMap/Tile.java
new file mode 100644
index 0000000..c339d47
--- /dev/null
+++ b/Knuckle's Adventure/src/TileMap/Tile.java
@@ -0,0 +1,22 @@
+package TileMap;
+
+import java.awt.image.BufferedImage;
+
+public class Tile {
+
+ private BufferedImage image;
+ private int type;
+
+ // tile types
+ public static final int NORMAL = 0;
+ public static final int BLOCKED = 1;
+
+ public Tile(BufferedImage image, int type) {
+ this.image = image;
+ this.type = type;
+ }
+
+ public BufferedImage getImage() { return image; }
+ public int getType() { return type; }
+
+}
diff --git a/Knuckle's Adventure/src/TileMap/TileMap.java b/Knuckle's Adventure/src/TileMap/TileMap.java
new file mode 100644
index 0000000..c9f54ce
--- /dev/null
+++ b/Knuckle's Adventure/src/TileMap/TileMap.java
@@ -0,0 +1,210 @@
+package TileMap;
+
+import java.awt.*;
+import java.awt.image.*;
+
+import java.io.*;
+import javax.imageio.ImageIO;
+
+import Main.GamePanel;
+
+public class TileMap {
+
+ // position
+ private double x;
+ private double y;
+
+ // bounds
+ private int xmin;
+ private int ymin;
+ private int xmax;
+ private int ymax;
+
+ private double tween;
+
+ // map
+ private int[][] map;
+ private int tileSize;
+ private int numRows;
+ private int numCols;
+ private int width;
+ private int height;
+
+ // tileset
+ private BufferedImage tileset;
+ private int numTilesAcross;
+ private Tile[][] tiles;
+
+ // drawing
+ private int rowOffset;
+ private int colOffset;
+ private int numRowsToDraw;
+ private int numColsToDraw;
+
+ public TileMap(int tileSize) {
+ this.tileSize = tileSize;
+ numRowsToDraw = GamePanel.HEIGHT / tileSize + 2;
+ numColsToDraw = GamePanel.WIDTH / tileSize + 2;
+ tween = 0.07;
+ }
+
+ public void loadTiles(String s) {
+
+ try {
+
+ tileset = ImageIO.read(
+ getClass().getResourceAsStream(s)
+ );
+ numTilesAcross = tileset.getWidth() / tileSize;
+ tiles = new Tile[2][numTilesAcross];
+
+ BufferedImage subimage;
+ for(int col = 0; col < numTilesAcross; col++) {
+ subimage = tileset.getSubimage(
+ col * tileSize,
+ 0,
+ tileSize,
+ tileSize
+ );
+ tiles[0][col] = new Tile(subimage, Tile.NORMAL);
+ subimage = tileset.getSubimage(
+ col * tileSize,
+ tileSize,
+ tileSize,
+ tileSize
+ );
+ tiles[1][col] = new Tile(subimage, Tile.BLOCKED);
+ }
+
+ }
+ catch(Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ public void loadMap(String s) {
+
+ try {
+
+ InputStream in = getClass().getResourceAsStream(s);
+ BufferedReader br = new BufferedReader(
+ new InputStreamReader(in)
+ );
+
+ numCols = Integer.parseInt(br.readLine());
+ numRows = Integer.parseInt(br.readLine());
+ map = new int[numRows][numCols];
+ width = numCols * tileSize;
+ height = numRows * tileSize;
+
+ xmin = GamePanel.WIDTH - width;
+ xmax = 0;
+ ymin = GamePanel.HEIGHT - height;
+ ymax = 0;
+
+ String delims = "\\s+";
+ for(int row = 0; row < numRows; row++) {
+ String line = br.readLine();
+ String[] tokens = line.split(delims);
+ for(int col = 0; col < numCols; col++) {
+ map[row][col] = Integer.parseInt(tokens[col]);
+ }
+ }
+
+ }
+ catch(Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ public int getTileSize() { return tileSize; }
+ public double getx() { return x; }
+ public double gety() { return y; }
+ public int getWidth() { return width; }
+ public int getHeight() { return height; }
+
+ public int getType(int row, int col) {
+ int rc = map[row][col];
+ int r = rc / numTilesAcross;
+ int c = rc % numTilesAcross;
+ return tiles[r][c].getType();
+ }
+
+ public void setTween(double d) { tween = d; }
+
+ public void setPosition(double x, double y) {
+
+ this.x += (x - this.x) * tween;
+ this.y += (y - this.y) * tween;
+
+ fixBounds();
+
+ colOffset = (int)-this.x / tileSize;
+ rowOffset = (int)-this.y / tileSize;
+
+ }
+
+ private void fixBounds() {
+ if(x < xmin) x = xmin;
+ if(y < ymin) y = ymin;
+ if(x > xmax) x = xmax;
+ if(y > ymax) y = ymax;
+ }
+
+ public void draw(Graphics2D g) {
+
+ for(
+ int row = rowOffset;
+ row < rowOffset + numRowsToDraw;
+ row++) {
+
+ if(row >= numRows) break;
+
+ for(
+ int col = colOffset;
+ col < colOffset + numColsToDraw;
+ col++) {
+
+ if(col >= numCols) break;
+
+ if(map[row][col] == 0) continue;
+
+ int rc = map[row][col];
+ int r = rc / numTilesAcross;
+ int c = rc % numTilesAcross;
+
+ g.drawImage(
+ tiles[r][c].getImage(),
+ (int)x + col * tileSize,
+ (int)y + row * tileSize,
+ null
+ );
+
+ }
+
+ }
+
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+