Initial commit.
This commit is contained in:
BIN
src/dk/itu/.DS_Store
vendored
Normal file
BIN
src/dk/itu/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
src/dk/itu/mario/.DS_Store
vendored
Normal file
BIN
src/dk/itu/mario/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
src/dk/itu/mario/MarioInterface/.DS_Store
vendored
Normal file
BIN
src/dk/itu/mario/MarioInterface/.DS_Store
vendored
Normal file
Binary file not shown.
10
src/dk/itu/mario/MarioInterface/Constraints.java
Normal file
10
src/dk/itu/mario/MarioInterface/Constraints.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package dk.itu.mario.MarioInterface;
|
||||
|
||||
public interface Constraints {
|
||||
// the submitted level should has exactly the following information
|
||||
public static int levelWidth= 320;
|
||||
public static int gaps = 10;
|
||||
public static int turtels = 7;
|
||||
public static int coinBlocks = 10;
|
||||
|
||||
}
|
||||
101
src/dk/itu/mario/MarioInterface/GamePlay.java
Normal file
101
src/dk/itu/mario/MarioInterface/GamePlay.java
Normal file
@@ -0,0 +1,101 @@
|
||||
package dk.itu.mario.MarioInterface;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
public class GamePlay implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public int completionTime; // counts only the current run on the level,
|
||||
// excluding death games
|
||||
public int totalTime;// sums all the time, including from previous games if
|
||||
// player died
|
||||
public int jumpsNumber; // total number of jumps
|
||||
public int duckNumber; // total number of ducks
|
||||
public int timeSpentDucking; // time spent in ducking mode
|
||||
public int timesPressedRun;// number of times the run key pressed
|
||||
public int timeSpentRunning; // total time spent running
|
||||
public int timeRunningRight; // total time spent running to the right
|
||||
public int timeRunningLeft;// total time spent running to the left
|
||||
public int emptyBlocksDestroyed; // number of empty blocks destroyed
|
||||
public int coinsCollected; // number of coins collected
|
||||
public int coinBlocksDestroyed; // number of coin block destroyed
|
||||
public int powerBlocksDestroyed; // number of power block destroyed
|
||||
public int kickedShells; // number of shells Mario kicked
|
||||
public int enemyKillByFire; // number of enemies killed by shooting them
|
||||
public int enemyKillByKickingShell; // number of enemies killed by kicking a
|
||||
// shell on them
|
||||
public int totalTimeLittleMode; // total time spent in little mode
|
||||
public int totalTimeLargeMode; // total time spent in large mode
|
||||
public int totalTimeFireMode; // total time spent in fire mode
|
||||
public int timesSwichingPower; // number of Times Switched Between Little,
|
||||
// Large or Fire Mario
|
||||
public double aimlessJumps; // number of jumps without a reason
|
||||
public double percentageBlocksDestroyed; // percentage of all blocks
|
||||
// destroyed
|
||||
public double percentageCoinBlocksDestroyed; // percentage of coin blocks
|
||||
// destroyed
|
||||
public double percentageEmptyBlockesDestroyed; // percentage of empty blocks
|
||||
// destroyed
|
||||
public double percentagePowerBlockDestroyed; // percentage of power blocks
|
||||
// destroyed
|
||||
public double timesOfDeathByFallingIntoGap; // number of death by falling
|
||||
// into a gap
|
||||
public int totalEnemies; // total number of enemies
|
||||
public int totalEmptyBlocks; // total number of empty blocks
|
||||
public int totalCoinBlocks; // total number of coin blocks
|
||||
public int totalpowerBlocks; // total number of power blocks
|
||||
public int totalCoins; // total number of coins
|
||||
public int timesOfDeathByRedTurtle; // number of times Mario died by red
|
||||
// turtle
|
||||
public int timesOfDeathByGoomba; // number of times Mario died by Goomba
|
||||
public int timesOfDeathByGreenTurtle; // number of times Mario died by green
|
||||
// turtle
|
||||
public int timesOfDeathByArmoredTurtle; // number of times Mario died by
|
||||
// Armored turtle
|
||||
public int timesOfDeathByJumpFlower; // number of times Mario died by Jump
|
||||
// Flower
|
||||
public int timesOfDeathByCannonBall; // number of time Mario died by Cannon
|
||||
// Ball
|
||||
public int timesOfDeathByChompFlower; // number of times Mario died by Chomp
|
||||
// Flower
|
||||
public int RedTurtlesKilled; // number of Red Turtle Mario killed
|
||||
public int GreenTurtlesKilled;// number of Green Turtle Mario killed
|
||||
public int ArmoredTurtlesKilled; // number of Armored Turtle Mario killed
|
||||
public int GoombasKilled; // number of Goombas Mario killed
|
||||
public int CannonBallKilled; // number of Cannon Ball Mario killed
|
||||
public int JumpFlowersKilled; // number of Jump Flower Mario killed
|
||||
public int ChompFlowersKilled; // number of Chomp Flower Mario killed
|
||||
|
||||
public void write(String fileName) {
|
||||
ObjectOutputStream out = null;
|
||||
try {
|
||||
FileOutputStream fos = new FileOutputStream(fileName);
|
||||
out = new ObjectOutputStream(fos);
|
||||
out.writeObject(this);
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static GamePlay read(String fileName) {
|
||||
FileInputStream fis = null;
|
||||
ObjectInputStream in = null;
|
||||
GamePlay gp = null;
|
||||
try {
|
||||
fis = new FileInputStream(fileName);
|
||||
in = new ObjectInputStream(fis);
|
||||
gp = (GamePlay) in.readObject();
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
return gp;
|
||||
}
|
||||
}
|
||||
12
src/dk/itu/mario/MarioInterface/LevelGenerator.java
Normal file
12
src/dk/itu/mario/MarioInterface/LevelGenerator.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package dk.itu.mario.MarioInterface;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
||||
public interface LevelGenerator {
|
||||
|
||||
//Use one of these methods to generate your level
|
||||
|
||||
public LevelInterface generateLevel (GamePlay playerMetrics);
|
||||
public LevelInterface generateLevel (String detailedInfo);
|
||||
}
|
||||
41
src/dk/itu/mario/MarioInterface/LevelInterface.java
Normal file
41
src/dk/itu/mario/MarioInterface/LevelInterface.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package dk.itu.mario.MarioInterface;
|
||||
|
||||
import dk.itu.mario.engine.sprites.SpriteTemplate;
|
||||
|
||||
public interface LevelInterface {
|
||||
|
||||
public static byte[] TILE_BEHAVIORS = new byte[256];
|
||||
|
||||
public static final int TYPE_OVERGROUND = 0;
|
||||
public static final int TYPE_UNDERGROUND = 1;
|
||||
public static final int TYPE_CASTLE = 2;
|
||||
|
||||
public static final int BIT_BLOCK_UPPER = 1 << 0;
|
||||
public static final int BIT_BLOCK_ALL = 1 << 1;
|
||||
public static final int BIT_BLOCK_LOWER = 1 << 2;
|
||||
public static final int BIT_SPECIAL = 1 << 3; //mashroom or flower
|
||||
public static final int BIT_BUMPABLE = 1 << 4;
|
||||
public static final int BIT_BREAKABLE = 1 << 5;
|
||||
public static final int BIT_PICKUPABLE = 1 << 6;
|
||||
public static final int BIT_ANIMATED = 1 << 7;
|
||||
|
||||
public void tick();
|
||||
|
||||
//Map of WIDTH * HEIGHT that contains the level's design
|
||||
public byte[][] getMap();
|
||||
|
||||
//Map of WIDTH * HEIGHT and contains the placement and type enemies
|
||||
public SpriteTemplate[][] getSpriteTemplates();
|
||||
|
||||
public int getWidth();
|
||||
|
||||
public int getHeight();
|
||||
|
||||
//These are the place where the level ends
|
||||
public int getxExit();
|
||||
|
||||
public int getyExit();
|
||||
|
||||
public String getName();
|
||||
|
||||
}
|
||||
BIN
src/dk/itu/mario/engine/.DS_Store
vendored
Normal file
BIN
src/dk/itu/mario/engine/.DS_Store
vendored
Normal file
Binary file not shown.
27
src/dk/itu/mario/engine/ArgParser.java
Normal file
27
src/dk/itu/mario/engine/ArgParser.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package dk.itu.mario.engine;
|
||||
|
||||
public class ArgParser {
|
||||
public static ParsedArgs parse(String[] cmdLineArgs) {
|
||||
ParsedArgs parsedArgs = new ParsedArgs();
|
||||
for (int i = 0; i < cmdLineArgs.length; i++) {
|
||||
if (cmdLineArgs[i].toUpperCase().startsWith("GENERATOR=")) {
|
||||
String generatorClass = cmdLineArgs[i].split("=")[1];
|
||||
parsedArgs.setGeneratorClass(generatorClass);
|
||||
System.out.println("Generator class set to: " + generatorClass);
|
||||
} else if (cmdLineArgs[i].toUpperCase().startsWith("SEED=")) {
|
||||
String levelRandSeed = cmdLineArgs[i].split("=")[1];
|
||||
if (parsedArgs.setLevelRandSeed(levelRandSeed)) {
|
||||
System.out.println("Level randomizer seed set to: " + levelRandSeed);
|
||||
} else {
|
||||
System.out.println("Unable to parse value of levelRandSeed: "
|
||||
+ levelRandSeed +". Keeping default value of: "
|
||||
+ parsedArgs.getLevelRandSeed());
|
||||
}
|
||||
} else if (cmdLineArgs[i].toUpperCase().startsWith("VIDEO=")) {
|
||||
String videoFileName = cmdLineArgs[i].split("=")[1];
|
||||
parsedArgs.setVideoFileName(videoFileName);
|
||||
}
|
||||
}
|
||||
return parsedArgs;
|
||||
}
|
||||
}
|
||||
192
src/dk/itu/mario/engine/Art.java
Normal file
192
src/dk/itu/mario/engine/Art.java
Normal file
@@ -0,0 +1,192 @@
|
||||
package dk.itu.mario.engine;
|
||||
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Image;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.sound.midi.MidiSystem;
|
||||
import javax.sound.midi.Sequence;
|
||||
import javax.sound.midi.Sequencer;
|
||||
|
||||
|
||||
import dk.itu.mario.engine.sonar.SonarSoundEngine;
|
||||
import dk.itu.mario.engine.sonar.sample.SonarSample;
|
||||
import java.io.InputStream;
|
||||
|
||||
|
||||
public class Art
|
||||
{
|
||||
public static final int SAMPLE_BREAK_BLOCK = 0;
|
||||
public static final int SAMPLE_GET_COIN = 1;
|
||||
public static final int SAMPLE_MARIO_JUMP = 2;
|
||||
public static final int SAMPLE_MARIO_STOMP = 3;
|
||||
public static final int SAMPLE_MARIO_KICK = 4;
|
||||
public static final int SAMPLE_MARIO_POWER_UP = 5;
|
||||
public static final int SAMPLE_MARIO_POWER_DOWN = 6;
|
||||
public static final int SAMPLE_MARIO_DEATH = 7;
|
||||
public static final int SAMPLE_ITEM_SPROUT = 8;
|
||||
public static final int SAMPLE_CANNON_FIRE = 9;
|
||||
public static final int SAMPLE_SHELL_BUMP = 10;
|
||||
public static final int SAMPLE_LEVEL_EXIT = 11;
|
||||
public static final int SAMPLE_MARIO_1UP = 12;
|
||||
public static final int SAMPLE_MARIO_FIREBALL = 13;
|
||||
|
||||
public static Image[][] mario;
|
||||
public static Image[][] smallMario;
|
||||
public static Image[][] fireMario;
|
||||
public static Image[][] enemies;
|
||||
public static Image[][] items;
|
||||
public static Image[][] level;
|
||||
public static Image[][] particles;
|
||||
public static Image[][] font;
|
||||
public static Image[][] bg;
|
||||
public static Image[][] map;
|
||||
public static Image[][] endScene;
|
||||
public static Image[][] gameOver;
|
||||
public static Image logo;
|
||||
public static Image titleScreen;
|
||||
public static Image keys, abkey;
|
||||
|
||||
public static SonarSample[] samples = new SonarSample[100];
|
||||
|
||||
private static Sequence[] songs = new Sequence[10];
|
||||
private static Sequencer sequencer;
|
||||
|
||||
public static boolean mute = false;
|
||||
private static final String PREFIX="/res";
|
||||
|
||||
|
||||
public static void init(GraphicsConfiguration gc, SonarSoundEngine sound)
|
||||
{
|
||||
try
|
||||
{
|
||||
mario = cutImage(gc, PREFIX+"/mariosheet.png", 32, 32);
|
||||
smallMario = cutImage(gc, PREFIX+"/smallmariosheet.png", 16, 16);
|
||||
fireMario = cutImage(gc, PREFIX+"/firemariosheet.png", 32, 32);
|
||||
enemies = cutImage(gc, PREFIX+"/enemysheet.png", 16, 32);
|
||||
items = cutImage(gc,PREFIX+ "/itemsheet.png", 16, 16);
|
||||
level = cutImage(gc, PREFIX+"/mapsheet.png", 16, 16);
|
||||
map = cutImage(gc, PREFIX+"/worldmap.png", 16, 16);
|
||||
particles = cutImage(gc, PREFIX+"/particlesheet.png", 8, 8);
|
||||
bg = cutImage(gc,PREFIX+ "/bgsheet.png", 32, 32);
|
||||
logo = getImage(gc, PREFIX+"/logo.gif");
|
||||
titleScreen = getImage(gc, PREFIX+"/title.gif");
|
||||
font = cutImage(gc, PREFIX+"/font.gif", 8, 8);
|
||||
endScene = cutImage(gc,PREFIX+ "/endscene.gif", 96, 96);
|
||||
gameOver = cutImage(gc, PREFIX+"/gameovergost.gif", 96, 64);
|
||||
keys = getImage(gc, PREFIX+"/keys.png");
|
||||
abkey = getImage(gc, PREFIX+"/abkey.png");
|
||||
|
||||
if (sound != null)
|
||||
{
|
||||
samples[SAMPLE_BREAK_BLOCK] = sound.loadSample(PREFIX+"/snd/breakblock.wav");
|
||||
samples[SAMPLE_GET_COIN] = sound.loadSample(PREFIX+"/snd/coin.wav");
|
||||
samples[SAMPLE_MARIO_JUMP] = sound.loadSample(PREFIX+"/snd/jump.wav");
|
||||
samples[SAMPLE_MARIO_STOMP] = sound.loadSample(PREFIX+"/snd/stomp.wav");
|
||||
samples[SAMPLE_MARIO_KICK] = sound.loadSample(PREFIX+"/snd/kick.wav");
|
||||
samples[SAMPLE_MARIO_POWER_UP] = sound.loadSample(PREFIX+"/snd/powerup.wav");
|
||||
samples[SAMPLE_MARIO_POWER_DOWN] = sound.loadSample(PREFIX+"/snd/powerdown.wav");
|
||||
samples[SAMPLE_MARIO_DEATH] = sound.loadSample(PREFIX+"/snd/death.wav");
|
||||
samples[SAMPLE_ITEM_SPROUT] = sound.loadSample(PREFIX+"/snd/sprout.wav");
|
||||
samples[SAMPLE_CANNON_FIRE] = sound.loadSample(PREFIX+"/snd/cannon.wav");
|
||||
samples[SAMPLE_SHELL_BUMP] = sound.loadSample(PREFIX+"/snd/bump.wav");
|
||||
samples[SAMPLE_LEVEL_EXIT] = sound.loadSample(PREFIX+"/snd/exit.wav");
|
||||
samples[SAMPLE_MARIO_1UP] = sound.loadSample(PREFIX+"/snd/1-up.wav");
|
||||
samples[SAMPLE_MARIO_FIREBALL] = sound.loadSample(PREFIX+"/snd/fireball.wav");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
sequencer = MidiSystem.getSequencer();
|
||||
sequencer.open();
|
||||
songs[0] = MidiSystem.getSequence(Art.class.getResourceAsStream(PREFIX+"/mus/smb3map1.mid"));
|
||||
songs[1] = MidiSystem.getSequence(Art.class.getResourceAsStream(PREFIX+"/mus/smwovr1.mid"));
|
||||
songs[2] = MidiSystem.getSequence(Art.class.getResourceAsStream(PREFIX+"/mus/smb3undr.mid"));
|
||||
songs[3] = MidiSystem.getSequence(Art.class.getResourceAsStream(PREFIX+"/mus/smwfortress.mid"));
|
||||
songs[4] = MidiSystem.getSequence(Art.class.getResourceAsStream(PREFIX+"/mus/smwtitle.mid"));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
sequencer = null;
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static Image getImage(GraphicsConfiguration gc, String imageName) throws IOException
|
||||
{
|
||||
InputStream p=Art.class.getResourceAsStream(imageName);
|
||||
BufferedImage source = ImageIO.read(p);
|
||||
Image image = gc.createCompatibleImage(source.getWidth(), source.getHeight(), Transparency.BITMASK);
|
||||
Graphics2D g = (Graphics2D) image.getGraphics();
|
||||
g.setComposite(AlphaComposite.Src);
|
||||
g.drawImage(source, 0, 0, null);
|
||||
g.dispose();
|
||||
return image;
|
||||
}
|
||||
|
||||
private static Image[][] cutImage(GraphicsConfiguration gc, String imageName, int xSize, int ySize) throws IOException
|
||||
{
|
||||
Image source = getImage(gc, imageName);
|
||||
Image[][] images = new Image[source.getWidth(null) / xSize][source.getHeight(null) / ySize];
|
||||
for (int x = 0; x < source.getWidth(null) / xSize; x++)
|
||||
{
|
||||
for (int y = 0; y < source.getHeight(null) / ySize; y++)
|
||||
{
|
||||
Image image = gc.createCompatibleImage(xSize, ySize, Transparency.BITMASK);
|
||||
Graphics2D g = (Graphics2D) image.getGraphics();
|
||||
g.setComposite(AlphaComposite.Src);
|
||||
g.drawImage(source, -x * xSize, -y * ySize, null);
|
||||
g.dispose();
|
||||
images[x][y] = image;
|
||||
}
|
||||
}
|
||||
|
||||
return images;
|
||||
}
|
||||
|
||||
public static void startMusic(int song)
|
||||
{
|
||||
if(!mute){
|
||||
stopMusic();
|
||||
if (sequencer != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
sequencer.open();
|
||||
sequencer.setSequence((Sequence)null);
|
||||
sequencer.setSequence(songs[song]);
|
||||
sequencer.setLoopCount(Sequencer.LOOP_CONTINUOUSLY);
|
||||
sequencer.start();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void stopMusic()
|
||||
{
|
||||
if (sequencer != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
sequencer.stop();
|
||||
sequencer.close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
103
src/dk/itu/mario/engine/BgRenderer.java
Normal file
103
src/dk/itu/mario/engine/BgRenderer.java
Normal file
@@ -0,0 +1,103 @@
|
||||
package dk.itu.mario.engine;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Random;
|
||||
|
||||
|
||||
import dk.itu.mario.level.Level;
|
||||
|
||||
|
||||
public class BgRenderer
|
||||
{
|
||||
private int xCam;
|
||||
private int yCam;
|
||||
private Image image;
|
||||
private Graphics2D g;
|
||||
private static final Color transparent = new Color(0, 0, 0, 0);
|
||||
private Level level;
|
||||
|
||||
private Random random = new Random();
|
||||
public boolean renderBehaviors = false;
|
||||
|
||||
private int width;
|
||||
private int height;
|
||||
private int distance;
|
||||
|
||||
public BgRenderer(Level level, GraphicsConfiguration graphicsConfiguration, int width, int height, int distance)
|
||||
{
|
||||
this.distance = distance;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
this.level = level;
|
||||
image = graphicsConfiguration.createCompatibleImage(width, height, Transparency.BITMASK);
|
||||
g = (Graphics2D) image.getGraphics();
|
||||
g.setComposite(AlphaComposite.Src);
|
||||
|
||||
updateArea(0, 0, width, height);
|
||||
}
|
||||
|
||||
public void setCam(int xCam, int yCam)
|
||||
{
|
||||
xCam /= distance;
|
||||
yCam /= distance;
|
||||
int xCamD = this.xCam - xCam;
|
||||
int yCamD = this.yCam - yCam;
|
||||
this.xCam = xCam;
|
||||
this.yCam = yCam;
|
||||
|
||||
g.setComposite(AlphaComposite.Src);
|
||||
g.copyArea(0, 0, width, height, xCamD, yCamD);
|
||||
|
||||
if (xCamD < 0)
|
||||
{
|
||||
if (xCamD < -width) xCamD = -width;
|
||||
updateArea(width + xCamD, 0, -xCamD, height);
|
||||
}
|
||||
else if (xCamD > 0)
|
||||
{
|
||||
if (xCamD > width) xCamD = width;
|
||||
updateArea(0, 0, xCamD, height);
|
||||
}
|
||||
|
||||
if (yCamD < 0)
|
||||
{
|
||||
if (yCamD < -width) yCamD = -width;
|
||||
updateArea(0, height + yCamD, width, -yCamD);
|
||||
}
|
||||
else if (yCamD > 0)
|
||||
{
|
||||
if (yCamD > width) yCamD = width;
|
||||
updateArea(0, 0, width, yCamD);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateArea(int x0, int y0, int w, int h)
|
||||
{
|
||||
g.setBackground(transparent);
|
||||
g.clearRect(x0, y0, w, h);
|
||||
int xTileStart = (x0 + xCam) / 32;
|
||||
int yTileStart = (y0 + yCam) / 32;
|
||||
int xTileEnd = (x0 + xCam + w) / 32;
|
||||
int yTileEnd = (y0 + yCam + h) / 32;
|
||||
for (int x = xTileStart; x <= xTileEnd; x++)
|
||||
{
|
||||
for (int y = yTileStart; y <= yTileEnd; y++)
|
||||
{
|
||||
int b = level.getBlock(x, y) & 0xff;
|
||||
g.drawImage(Art.bg[b % 8][b / 8], (x << 5) - xCam, (y << 5) - yCam-16, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void render(Graphics g, int tick, float alpha)
|
||||
{
|
||||
g.drawImage(image, 0, 0, null);
|
||||
}
|
||||
|
||||
public void setLevel(Level level)
|
||||
{
|
||||
this.level = level;
|
||||
updateArea(0, 0, width, height);
|
||||
}
|
||||
}
|
||||
56
src/dk/itu/mario/engine/ConstraintsChecker.java
Normal file
56
src/dk/itu/mario/engine/ConstraintsChecker.java
Normal file
@@ -0,0 +1,56 @@
|
||||
package dk.itu.mario.engine;
|
||||
|
||||
import dk.itu.mario.level.Level;
|
||||
import dk.itu.mario.MarioInterface.Constraints;
|
||||
import dk.itu.mario.engine.sprites.SpriteTemplate;
|
||||
|
||||
public final class ConstraintsChecker {
|
||||
|
||||
public static boolean check(Level level){
|
||||
if(level.getWidth() != Constraints.levelWidth)
|
||||
return false;
|
||||
//check the number of gaps
|
||||
int levelGaps = 0, bcoins = 0;
|
||||
for (int i = 0; i < level.getWidth(); i++) {
|
||||
if (level.getBlock(i, level.getHeight()) == 0){
|
||||
levelGaps++;
|
||||
while (i<level.getWidth() && level.getBlock(i, level.getHeight())==0){
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// if(levelGaps != Constraints.gaps)
|
||||
// return false;
|
||||
|
||||
//check the number of TURTLES
|
||||
int tur = 0;
|
||||
for (int i = 0; i < level.getSpriteTemplate().length; i++) {
|
||||
|
||||
SpriteTemplate[] st = (SpriteTemplate[])level.getSpriteTemplate()[i];
|
||||
for (int j = 0; j < st.length; j++) {
|
||||
if(st[j]!=null){
|
||||
int t = ((SpriteTemplate)st[j]).type;
|
||||
if(t== SpriteTemplate.RED_TURTLE || t == SpriteTemplate.GREEN_TURTLE || t == SpriteTemplate.ARMORED_TURTLE)
|
||||
tur++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// if(tur != Constraints.turtels)
|
||||
// return false;
|
||||
|
||||
//check the number of coin blocks
|
||||
for (int i = 0; i < level.getWidth(); i++) {
|
||||
for (int j = 0; j < level.getHeight(); j++) {
|
||||
byte block = level.getBlock(i, j);
|
||||
if ((Level.TILE_BEHAVIORS[block & 0xff] & Level.BIT_BUMPABLE) > 0)
|
||||
if (! (((Level.TILE_BEHAVIORS[block & 0xff]) & Level.BIT_SPECIAL) > 0))
|
||||
bcoins++;
|
||||
}
|
||||
}
|
||||
// if(bcoins != Constraints.coinBlocks)
|
||||
// return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
1138
src/dk/itu/mario/engine/DataRecorder.java
Normal file
1138
src/dk/itu/mario/engine/DataRecorder.java
Normal file
File diff suppressed because it is too large
Load Diff
26
src/dk/itu/mario/engine/LevelFactory.java
Normal file
26
src/dk/itu/mario/engine/LevelFactory.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package dk.itu.mario.engine;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import dk.itu.mario.level.Level;
|
||||
|
||||
public abstract class LevelFactory {
|
||||
|
||||
private static Map<String, Level> levels = new HashMap<String, Level>();
|
||||
|
||||
public static void register(String name,Level level){
|
||||
levels.put(name, level);
|
||||
}
|
||||
|
||||
public static Level retrieve(String name){
|
||||
return levels.get(name);
|
||||
}
|
||||
|
||||
public static Iterator<String> getKeyset(){
|
||||
return levels.keySet().iterator();
|
||||
}
|
||||
|
||||
public static Map getLevelsMap(){
|
||||
return levels;
|
||||
}
|
||||
}
|
||||
212
src/dk/itu/mario/engine/LevelRenderer.java
Normal file
212
src/dk/itu/mario/engine/LevelRenderer.java
Normal file
@@ -0,0 +1,212 @@
|
||||
package dk.itu.mario.engine;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Random;
|
||||
|
||||
|
||||
import dk.itu.mario.level.Level;
|
||||
|
||||
|
||||
public class LevelRenderer
|
||||
{
|
||||
private int xCam;
|
||||
private int yCam;
|
||||
private Image image;
|
||||
private Graphics2D g;
|
||||
private static final Color transparent = new Color(0, 0, 0, 0);
|
||||
private Level level;
|
||||
|
||||
private Random random = new Random();
|
||||
public boolean renderBehaviors = false;
|
||||
|
||||
public int width;
|
||||
public int height;
|
||||
|
||||
public LevelRenderer(Level level, GraphicsConfiguration graphicsConfiguration, int width, int height)
|
||||
{
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
this.level = level;
|
||||
image = graphicsConfiguration.createCompatibleImage(width, height, Transparency.BITMASK);
|
||||
g = (Graphics2D) image.getGraphics();
|
||||
g.setComposite(AlphaComposite.Src);
|
||||
|
||||
updateArea(0, 0, width, height);
|
||||
}
|
||||
|
||||
public void setCam(int xCam, int yCam)
|
||||
{
|
||||
int xCamD = this.xCam - xCam;
|
||||
int yCamD = this.yCam - yCam;
|
||||
this.xCam = xCam;
|
||||
this.yCam = yCam;
|
||||
|
||||
g.setComposite(AlphaComposite.Src);
|
||||
g.copyArea(0, 0, width, height, xCamD, yCamD);
|
||||
|
||||
if (xCamD < 0)
|
||||
{
|
||||
if (xCamD < -width) xCamD = -width;
|
||||
updateArea(width + xCamD, 0, -xCamD, height);
|
||||
}
|
||||
else if (xCamD > 0)
|
||||
{
|
||||
if (xCamD > width) xCamD = width;
|
||||
updateArea(0, 0, xCamD, height);
|
||||
}
|
||||
|
||||
if (yCamD < 0)
|
||||
{
|
||||
if (yCamD < -width) yCamD = -width;
|
||||
updateArea(0, height + yCamD, width, -yCamD);
|
||||
}
|
||||
else if (yCamD > 0)
|
||||
{
|
||||
if (yCamD > width) yCamD = width;
|
||||
updateArea(0, 0, width, yCamD);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateArea(int x0, int y0, int w, int h)
|
||||
{
|
||||
g.setBackground(transparent);
|
||||
g.clearRect(x0, y0, w, h);
|
||||
int xTileStart = (x0 + xCam) / 16;
|
||||
int yTileStart = (y0 + yCam) / 16;
|
||||
int xTileEnd = (x0 + xCam + w) / 16;
|
||||
int yTileEnd = (y0 + yCam + h) / 16;
|
||||
for (int x = xTileStart; x <= xTileEnd; x++)
|
||||
{
|
||||
for (int y = yTileStart; y <= yTileEnd; y++)
|
||||
{
|
||||
int b = level.getBlock(x, y) & 0xff;
|
||||
if (((Level.TILE_BEHAVIORS[b]) & Level.BIT_ANIMATED) == 0)
|
||||
{
|
||||
g.drawImage(Art.level[b % 16][b / 16], (x << 4) - xCam, (y << 4) - yCam, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void render(Graphics g, int tick, float alpha)
|
||||
{
|
||||
g.drawImage(image, 0, 0, null);
|
||||
|
||||
for (int x = xCam / 16; x <= (xCam + width) / 16; x++)
|
||||
for (int y = yCam / 16; y <= (yCam + height) / 16; y++)
|
||||
{
|
||||
byte b = level.getBlock(x, y);
|
||||
|
||||
if (((Level.TILE_BEHAVIORS[b & 0xff]) & Level.BIT_ANIMATED) > 0)
|
||||
{
|
||||
int animTime = (tick / 3) % 4;
|
||||
|
||||
if ((b % 16) / 4 == 0 && b / 16 == 1)
|
||||
{
|
||||
animTime = (tick / 2 + (x + y) / 8) % 20;
|
||||
if (animTime > 3) animTime = 0;
|
||||
}
|
||||
if ((b % 16) / 4 == 3 && b / 16 == 0)
|
||||
{
|
||||
animTime = 2;
|
||||
}
|
||||
int yo = 0;
|
||||
// if (x >= 0 && y >= 0 && x < level.getWidth() && y < level.getyHeight()) yo = level.data[x][y];
|
||||
if (yo > 0) yo = (int) (Math.sin((yo - alpha) / 4.0f * Math.PI) * 8);
|
||||
g.drawImage(Art.level[(b % 16) / 4 * 4 + animTime][b / 16], (x << 4) - xCam, (y << 4) - yCam - yo, null);
|
||||
}
|
||||
|
||||
/* else if (b == Level.TILE_BONUS)
|
||||
{
|
||||
int animTime = (tick / 3) % 4;
|
||||
int yo = 0;
|
||||
if (x >= 0 && y >= 0 && x < level.width && y < level.height) yo = level.data[x][y];
|
||||
if (yo > 0) yo = (int) (Math.sin((yo - alpha) / 4.0f * Math.PI) * 8);
|
||||
g.drawImage(Art.mapSprites[(4 + animTime)][0], (x << 4) - xCam, (y << 4) - yCam - yo, null);
|
||||
}*/
|
||||
|
||||
if (renderBehaviors)
|
||||
{
|
||||
if (((Level.TILE_BEHAVIORS[b & 0xff]) & Level.BIT_BLOCK_UPPER) > 0)
|
||||
{
|
||||
g.setColor(Color.RED);
|
||||
g.fillRect((x << 4) - xCam, (y << 4) - yCam, 16, 2);
|
||||
}
|
||||
if (((Level.TILE_BEHAVIORS[b & 0xff]) & Level.BIT_BLOCK_ALL) > 0)
|
||||
{
|
||||
g.setColor(Color.RED);
|
||||
g.fillRect((x << 4) - xCam, (y << 4) - yCam, 16, 2);
|
||||
g.fillRect((x << 4) - xCam, (y << 4) - yCam + 14, 16, 2);
|
||||
g.fillRect((x << 4) - xCam, (y << 4) - yCam, 2, 16);
|
||||
g.fillRect((x << 4) - xCam + 14, (y << 4) - yCam, 2, 16);
|
||||
}
|
||||
if (((Level.TILE_BEHAVIORS[b & 0xff]) & Level.BIT_BLOCK_LOWER) > 0)
|
||||
{
|
||||
g.setColor(Color.RED);
|
||||
g.fillRect((x << 4) - xCam, (y << 4) - yCam + 14, 16, 2);
|
||||
}
|
||||
if (((Level.TILE_BEHAVIORS[b & 0xff]) & Level.BIT_SPECIAL) > 0)
|
||||
{
|
||||
g.setColor(Color.PINK);
|
||||
g.fillRect((x << 4) - xCam + 2 + 4, (y << 4) - yCam + 2 + 4, 4, 4);
|
||||
}
|
||||
if (((Level.TILE_BEHAVIORS[b & 0xff]) & Level.BIT_BUMPABLE) > 0)
|
||||
{
|
||||
g.setColor(Color.BLUE);
|
||||
g.fillRect((x << 4) - xCam + 2, (y << 4) - yCam + 2, 4, 4);
|
||||
}
|
||||
if (((Level.TILE_BEHAVIORS[b & 0xff]) & Level.BIT_BREAKABLE) > 0)
|
||||
{
|
||||
g.setColor(Color.GREEN);
|
||||
g.fillRect((x << 4) - xCam + 2 + 4, (y << 4) - yCam + 2, 4, 4);
|
||||
}
|
||||
if (((Level.TILE_BEHAVIORS[b & 0xff]) & Level.BIT_PICKUPABLE) > 0)
|
||||
{
|
||||
g.setColor(Color.YELLOW);
|
||||
g.fillRect((x << 4) - xCam + 2, (y << 4) - yCam + 2 + 4, 4, 4);
|
||||
}
|
||||
if (((Level.TILE_BEHAVIORS[b & 0xff]) & Level.BIT_ANIMATED) > 0)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void repaint(int x, int y, int w, int h)
|
||||
{
|
||||
updateArea(x * 16 - xCam, y * 16 - yCam, w * 16, h * 16);
|
||||
}
|
||||
|
||||
public void setLevel(Level level)
|
||||
{
|
||||
this.level = level;
|
||||
updateArea(0, 0, width, height);
|
||||
}
|
||||
|
||||
public void renderExit0(Graphics g, int tick, float alpha, boolean bar)
|
||||
{
|
||||
for (int y = level.getyExit() - 8; y < level.getyExit(); y++)
|
||||
{
|
||||
g.drawImage(Art.level[12][y == level.getyExit() - 8 ? 4 : 5], (level.getxExit() << 4) - xCam - 16, (y << 4) - yCam, null);
|
||||
}
|
||||
int yh = level.getyExit() * 16 - (int) ((Math.sin((tick + alpha) / 20) * 0.5 + 0.5) * 7 * 16) - 8;
|
||||
if (bar)
|
||||
{
|
||||
g.drawImage(Art.level[12][3], (level.getxExit() << 4) - xCam - 16, yh - yCam, null);
|
||||
g.drawImage(Art.level[13][3], (level.getxExit() << 4) - xCam, yh - yCam, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void renderExit1(Graphics g, int tick, float alpha)
|
||||
{
|
||||
for (int y = level.getyExit() - 8; y < level.getyExit(); y++)
|
||||
{
|
||||
g.drawImage(Art.level[13][y == level.getyExit() - 8 ? 4 : 5], (level.getxExit() << 4) - xCam + 16, (y << 4) - yCam, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
306
src/dk/itu/mario/engine/MarioComponent.java
Normal file
306
src/dk/itu/mario/engine/MarioComponent.java
Normal file
@@ -0,0 +1,306 @@
|
||||
package dk.itu.mario.engine;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.awt.image.VolatileImage;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.sound.sampled.LineUnavailableException;
|
||||
import javax.swing.JComponent;
|
||||
|
||||
import dk.itu.mario.MarioInterface.LevelGenerator;
|
||||
import dk.itu.mario.engine.sonar.FakeSoundEngine;
|
||||
import dk.itu.mario.engine.sonar.SonarSoundEngine;
|
||||
import dk.itu.mario.engine.sprites.Mario;
|
||||
import dk.itu.mario.scene.LevelScene;
|
||||
import dk.itu.mario.scene.LevelSceneCustom;
|
||||
import dk.itu.mario.scene.LoseScene;
|
||||
import dk.itu.mario.scene.Scene;
|
||||
import dk.itu.mario.scene.WinScene;
|
||||
|
||||
public class MarioComponent extends JComponent implements Runnable,
|
||||
KeyListener, FocusListener, MouseListener {
|
||||
private static final long serialVersionUID = 739318775993206607L;
|
||||
|
||||
public static final int TICKS_PER_SECOND = 24;
|
||||
|
||||
public static final int EVOLVE_VERSION = 4;
|
||||
public static final int GAME_VERSION = 4;
|
||||
|
||||
private boolean running = false;
|
||||
private int width, height;
|
||||
private GraphicsConfiguration graphicsConfiguration;
|
||||
private Scene scene;
|
||||
private SonarSoundEngine sound;
|
||||
private boolean useScale2x = false;
|
||||
private boolean isCustom = false;
|
||||
private LevelGenerator levelGenerator;
|
||||
private Scale2x scale2x = new Scale2x(320, 240);
|
||||
|
||||
public MarioComponent(int width, int height, boolean isCustomized, LevelGenerator levelGenerator) {
|
||||
addFocusListener(this);
|
||||
addMouseListener(this);
|
||||
addKeyListener(this);
|
||||
|
||||
this.setFocusable(true);
|
||||
this.setEnabled(true);
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.isCustom = isCustomized;
|
||||
|
||||
Dimension size = new Dimension(width, height);
|
||||
setPreferredSize(size);
|
||||
setMinimumSize(size);
|
||||
setMaximumSize(size);
|
||||
|
||||
try {
|
||||
sound = new SonarSoundEngine(64);
|
||||
} catch (LineUnavailableException e) {
|
||||
e.printStackTrace();
|
||||
sound = new FakeSoundEngine();
|
||||
}
|
||||
this.setFocusable(true);
|
||||
this.levelGenerator = levelGenerator;
|
||||
LevelScene.bothPlayed = false;
|
||||
}
|
||||
|
||||
private void toggleKey(int keyCode, boolean isPressed) {
|
||||
if (scene == null) {
|
||||
return;
|
||||
}
|
||||
if (keyCode == KeyEvent.VK_LEFT) {
|
||||
scene.toggleKey(Mario.KEY_LEFT, isPressed);
|
||||
}
|
||||
if (keyCode == KeyEvent.VK_RIGHT) {
|
||||
scene.toggleKey(Mario.KEY_RIGHT, isPressed);
|
||||
}
|
||||
if (keyCode == KeyEvent.VK_DOWN) {
|
||||
scene.toggleKey(Mario.KEY_DOWN, isPressed);
|
||||
}
|
||||
if (keyCode == KeyEvent.VK_UP) {
|
||||
scene.toggleKey(Mario.KEY_UP, isPressed);
|
||||
}
|
||||
if (keyCode == KeyEvent.VK_A) {
|
||||
scene.toggleKey(Mario.KEY_SPEED, isPressed);
|
||||
}
|
||||
if (keyCode == KeyEvent.VK_S) {
|
||||
scene.toggleKey(Mario.KEY_JUMP, isPressed);
|
||||
}
|
||||
if (keyCode == KeyEvent.VK_ENTER) {
|
||||
scene.toggleKey(Mario.KEY_ENTER, isPressed);
|
||||
}
|
||||
if (isPressed && keyCode == KeyEvent.VK_F1) {
|
||||
useScale2x = !useScale2x;
|
||||
}
|
||||
|
||||
if (isPressed && keyCode == KeyEvent.VK_ESCAPE) {
|
||||
try {
|
||||
System.exit(1);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Unable to exit.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void paint(Graphics g) {
|
||||
super.paint(g);
|
||||
}
|
||||
|
||||
public void update(Graphics g) {
|
||||
}
|
||||
|
||||
public void start() {
|
||||
if (!running) {
|
||||
running = true;
|
||||
new Thread(this, "Game Thread").start();
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
Art.stopMusic();
|
||||
running = false;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
|
||||
graphicsConfiguration = getGraphicsConfiguration();
|
||||
|
||||
Art.init(graphicsConfiguration, sound);
|
||||
|
||||
VolatileImage image = createVolatileImage(320, 240);
|
||||
Graphics g = getGraphics();
|
||||
Graphics og = image.getGraphics();
|
||||
|
||||
int lastTick = -1;
|
||||
|
||||
long startTime = System.nanoTime();
|
||||
|
||||
float time = (System.nanoTime() - startTime) / 1000000000f;
|
||||
float now = time;
|
||||
float averagePassedTime = 0;
|
||||
|
||||
boolean naiveTiming = true;
|
||||
|
||||
///Not sure I understand the weird dichotomy between LevelScene and LevelInterface...
|
||||
randomLevel = new LevelSceneCustom(graphicsConfiguration, this,
|
||||
new Random().nextLong(), 0, 0, isCustom, levelGenerator);
|
||||
|
||||
Mario.fire = false;
|
||||
Mario.large = false;
|
||||
Mario.coins = 0;
|
||||
Mario.lives = 3;
|
||||
|
||||
randomLevel.init();
|
||||
randomLevel.setSound(sound);
|
||||
scene = randomLevel;
|
||||
///
|
||||
|
||||
while (running) {
|
||||
float lastTime = time;
|
||||
time = (System.nanoTime() - startTime) / 1000000000f;
|
||||
float passedTime = time - lastTime;
|
||||
|
||||
if (passedTime < 0)
|
||||
naiveTiming = false; // Stop relying on nanotime if it starts
|
||||
// skipping around in time (ie running
|
||||
// backwards at least once). This
|
||||
// sometimes happens on dual core amds.
|
||||
averagePassedTime = averagePassedTime * 0.9f + passedTime * 0.1f;
|
||||
|
||||
if (naiveTiming) {
|
||||
now = time;
|
||||
} else {
|
||||
now += averagePassedTime;
|
||||
}
|
||||
|
||||
int tick = (int) (now * TICKS_PER_SECOND);
|
||||
|
||||
if (lastTick == -1)
|
||||
lastTick = tick;
|
||||
|
||||
while (lastTick < tick) {
|
||||
scene.tick();
|
||||
|
||||
lastTick++;
|
||||
}
|
||||
|
||||
float alpha = (float) (now * TICKS_PER_SECOND - tick);
|
||||
sound.clientTick(alpha);
|
||||
|
||||
og.setColor(Color.WHITE);
|
||||
og.fillRect(0, 0, 320, 240);
|
||||
|
||||
scene.render(og, alpha);
|
||||
|
||||
if (!this.hasFocus() && tick / 4 % 2 == 0) {
|
||||
String msg = "CLICK TO PLAY";
|
||||
|
||||
drawString(og, msg, 160 - msg.length() * 4 + 1, 110 + 1, 0);
|
||||
drawString(og, msg, 160 - msg.length() * 4, 110, 7);
|
||||
}
|
||||
og.setColor(Color.BLACK);
|
||||
|
||||
if (width != 320 || height != 240) {
|
||||
|
||||
if (useScale2x) {
|
||||
g.drawImage(scale2x.scale(image), 0, 0, null);
|
||||
} else {
|
||||
g.drawImage(image, 0, 0, 640, 480, null);
|
||||
|
||||
}
|
||||
} else {
|
||||
g.drawImage(image, 0, 0, null);
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(5);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
|
||||
Art.stopMusic();
|
||||
}
|
||||
|
||||
private void drawString(Graphics g, String text, int x, int y, int c) {
|
||||
char[] ch = text.toCharArray();
|
||||
for (int i = 0; i < ch.length; i++) {
|
||||
g.drawImage(Art.font[ch[i] - 32][c], x + i * 8, y, null);
|
||||
}
|
||||
}
|
||||
|
||||
public void keyPressed(KeyEvent arg0) {
|
||||
toggleKey(arg0.getKeyCode(), true);
|
||||
}
|
||||
|
||||
public void keyReleased(KeyEvent arg0) {
|
||||
toggleKey(arg0.getKeyCode(), false);
|
||||
}
|
||||
|
||||
public void keyTyped(KeyEvent arg0) {
|
||||
}
|
||||
|
||||
public void focusGained(FocusEvent arg0) {
|
||||
}
|
||||
|
||||
public void focusLost(FocusEvent arg0) {
|
||||
}
|
||||
|
||||
public void levelWon() {
|
||||
}
|
||||
|
||||
public static final int OPTIMIZED_FIRST = 0;
|
||||
public static final int MINIMIZED_FIRST = 1;
|
||||
|
||||
private LevelScene randomLevel;
|
||||
|
||||
public void lose() {
|
||||
scene = new LoseScene();
|
||||
scene.setSound(sound);
|
||||
scene.init();
|
||||
}
|
||||
|
||||
public void win() {
|
||||
scene = new WinScene();
|
||||
scene.setSound(sound);
|
||||
scene.init();
|
||||
}
|
||||
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
}
|
||||
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
public void mouseExited(MouseEvent e) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
public void mousePressed(MouseEvent e) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
|
||||
while (!hasFocus()) {
|
||||
System.out.println("FORCE IT");
|
||||
requestFocus();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Must return the actual fill of the viewable components
|
||||
*/
|
||||
public Dimension getPreferredSize() {
|
||||
return new Dimension(width, height);
|
||||
}
|
||||
|
||||
}
|
||||
86
src/dk/itu/mario/engine/ParsedArgs.java
Normal file
86
src/dk/itu/mario/engine/ParsedArgs.java
Normal file
@@ -0,0 +1,86 @@
|
||||
package dk.itu.mario.engine;
|
||||
|
||||
import dk.itu.mario.MarioInterface.LevelGenerator;
|
||||
import dk.itu.mario.level.generator.CustomizedLevelGenerator;
|
||||
import dk.itu.mario.level.generator.MyLevelGenerator;
|
||||
import dk.itu.mario.level.generator.RandomLevelGenerator;
|
||||
|
||||
public class ParsedArgs {
|
||||
public static final String NO_GEN_ERR = "Generator class not specified (use generator=... argument).";
|
||||
|
||||
//Default values per Play class:
|
||||
private boolean custom = false;
|
||||
private boolean videoCaptureEnabled = false;
|
||||
private int levelRandSeed = (int) (Math.random() * Integer.MAX_VALUE);
|
||||
private String generatorClass = "MyLevel";
|
||||
private String videoFileName = "LevelGenerator";
|
||||
|
||||
public LevelGenerator createLevelGenerator() {
|
||||
if (generatorClass == null) {
|
||||
throw new UnsupportedOperationException(NO_GEN_ERR);
|
||||
}
|
||||
if ("MyLevel".equals(generatorClass)) {
|
||||
return new MyLevelGenerator();
|
||||
} else if ("CustomizedLevel".equalsIgnoreCase(generatorClass)) {
|
||||
return new CustomizedLevelGenerator();
|
||||
} else if ("RandomLevel".equalsIgnoreCase(generatorClass)) {
|
||||
return new RandomLevelGenerator();
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Cannot create LevelFactory for unrecognized class:" + generatorClass);
|
||||
}
|
||||
}
|
||||
|
||||
public String getGeneratorClass() {
|
||||
return generatorClass;
|
||||
}
|
||||
|
||||
public int getLevelRandSeed() {
|
||||
return levelRandSeed;
|
||||
}
|
||||
|
||||
public String getVideoFileName() {
|
||||
return videoFileName;
|
||||
}
|
||||
|
||||
public boolean isCustom() {
|
||||
return custom;
|
||||
}
|
||||
|
||||
public boolean isGeneratorClassSet() {
|
||||
return generatorClass != null;
|
||||
}
|
||||
|
||||
public boolean isVideoCaptureEnabled() {
|
||||
return videoCaptureEnabled;
|
||||
}
|
||||
|
||||
public void setGeneratorClass(String generatorClass) {
|
||||
if (generatorClass == null) {
|
||||
throw new UnsupportedOperationException(NO_GEN_ERR);
|
||||
}
|
||||
|
||||
this.generatorClass = generatorClass;
|
||||
|
||||
if ("MyLevel".equals(generatorClass)) {
|
||||
custom = true;
|
||||
} else if ("CustomizedLevel".equalsIgnoreCase(generatorClass)) {
|
||||
custom = true;
|
||||
} else {
|
||||
custom = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void setVideoFileName(String videoFileName) {
|
||||
this.videoFileName = videoFileName;
|
||||
this.videoCaptureEnabled = true;
|
||||
}
|
||||
|
||||
public boolean setLevelRandSeed(String randSeedString) {
|
||||
try {
|
||||
levelRandSeed = Integer.valueOf(randSeedString);
|
||||
return true;
|
||||
} catch (NumberFormatException nfe) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
30
src/dk/itu/mario/engine/Play.java
Normal file
30
src/dk/itu/mario/engine/Play.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package dk.itu.mario.engine;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Toolkit;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
|
||||
public class Play {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
JFrame frame = new JFrame("Mario Experience Showcase");
|
||||
ParsedArgs parsedArgs = ArgParser.parse(args);
|
||||
MarioComponent mario = new MarioComponent(640, 480, parsedArgs.isCustom(), parsedArgs.createLevelGenerator());
|
||||
|
||||
frame.setContentPane(mario);
|
||||
frame.setResizable(false);
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
frame.pack();
|
||||
|
||||
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
frame.setLocation((screenSize.width - frame.getWidth()) / 2,
|
||||
(screenSize.height - frame.getHeight()) / 2);
|
||||
|
||||
frame.setVisible(true);
|
||||
|
||||
mario.start();
|
||||
}
|
||||
|
||||
}
|
||||
130
src/dk/itu/mario/engine/Scale2x.java
Normal file
130
src/dk/itu/mario/engine/Scale2x.java
Normal file
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
* Scale2x.java
|
||||
*
|
||||
* Written by Markus Persson of Mojang Specifications for a super mario programming contest.
|
||||
* Implements the Scale2x algorithm described here: http://scale2x.sourceforge.net/algorithm.html
|
||||
* Works on any input image size, and uses a fancy border hack to prevent range checking.
|
||||
* It's fast enough for real time use on smaller images (320x240 and thereabouts)
|
||||
*
|
||||
* This code is public domain. Do whatever you want with it.
|
||||
*/
|
||||
package dk.itu.mario.engine;
|
||||
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Image;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBufferInt;
|
||||
|
||||
|
||||
public class Scale2x
|
||||
{
|
||||
private int width;
|
||||
private int height;
|
||||
|
||||
private BufferedImage sourceImage;
|
||||
private int[] sourcePixels;
|
||||
private Graphics sourceGraphics;
|
||||
|
||||
private BufferedImage targetImage;
|
||||
private int[] targetPixels;
|
||||
|
||||
/**
|
||||
* Creates a new Scale2x object. The new object will scale images of the specified size to images
|
||||
* that are twice as large.<br>
|
||||
*
|
||||
* @param width The width of the images to be scaled
|
||||
* @param height The height of the images to be scaled
|
||||
*/
|
||||
public Scale2x(int width, int height)
|
||||
{
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
// A border of one pixel in each direction, and one down, to avoid if statements in the scale loop
|
||||
sourceImage = new BufferedImage(width + 2, height + 3, BufferedImage.TYPE_INT_RGB);
|
||||
DataBufferInt sourceDataBuffer = (DataBufferInt) sourceImage.getRaster().getDataBuffer();
|
||||
sourcePixels = sourceDataBuffer.getData();
|
||||
sourceGraphics = sourceImage.getGraphics();
|
||||
|
||||
targetImage = new BufferedImage(width * 2, height * 2, BufferedImage.TYPE_INT_RGB);
|
||||
DataBufferInt targetDataBuffer = (DataBufferInt) targetImage.getRaster().getDataBuffer();
|
||||
targetPixels = targetDataBuffer.getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Scales an image and returns a twice as large image.<br>
|
||||
* This assumes the input image is of the dimensions specified in the Scale2x constructor.<br>
|
||||
* The returned image is a reference to the internal scale target in this Scale2x, so it
|
||||
* will get changed if you call this method again, so don't hold on to it for too long.<br>
|
||||
* In other words:<br>
|
||||
* <code>Image i0 = scale2x.scale(image0);<br>
|
||||
* Image i1 = scale2x.scale(image1);<br>
|
||||
* if (i0 == i1) System.exit(0); // Will always terminate</code><br>
|
||||
*
|
||||
* @param img The image to be scaled
|
||||
* @returns A scaled image. If you want that image to survive the next call to this method, make a copy of it.
|
||||
*/
|
||||
public Image scale(Image img)
|
||||
{
|
||||
// Offset the image by one pixel so there's a border around it.
|
||||
// This lets us avoid having to check that A-I are in range of the image before samping them
|
||||
sourceGraphics.drawImage(img, 1, 1, null);
|
||||
|
||||
int line = width + 2;
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
// Two lines of target pixel pointers
|
||||
int tp0 = y * width * 4 - 1;
|
||||
int tp1 = tp0 + width * 2;
|
||||
|
||||
// Three lines of source pixel pointers
|
||||
int sp0 = (y) * line;
|
||||
int sp1 = (y + 1) * line;
|
||||
int sp2 = (y + 2) * line;
|
||||
|
||||
// Fill the initial A-I values
|
||||
int A = sourcePixels[sp0];
|
||||
int B = sourcePixels[++sp0];
|
||||
int C = sourcePixels[++sp0];
|
||||
int D = sourcePixels[sp1];
|
||||
int E = sourcePixels[++sp1];
|
||||
int F = sourcePixels[++sp1];
|
||||
int G = sourcePixels[sp2];
|
||||
int H = sourcePixels[++sp2];
|
||||
int I = sourcePixels[++sp2];
|
||||
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
if (B != H && D != F)
|
||||
{
|
||||
targetPixels[++tp0] = D == B ? D : E;
|
||||
targetPixels[++tp0] = B == F ? F : E;
|
||||
targetPixels[++tp1] = D == H ? D : E;
|
||||
targetPixels[++tp1] = H == F ? F : E;
|
||||
}
|
||||
else
|
||||
{
|
||||
targetPixels[++tp0] = E;
|
||||
targetPixels[++tp0] = E;
|
||||
targetPixels[++tp1] = E;
|
||||
targetPixels[++tp1] = E;
|
||||
}
|
||||
|
||||
// Scroll A-I left
|
||||
A = B;
|
||||
B = C;
|
||||
D = E;
|
||||
E = F;
|
||||
G = H;
|
||||
H = I;
|
||||
|
||||
// Resample rightmost edge
|
||||
C = sourcePixels[++sp0];
|
||||
F = sourcePixels[++sp1];
|
||||
I = sourcePixels[++sp2];
|
||||
}
|
||||
}
|
||||
|
||||
return targetImage;
|
||||
}
|
||||
}
|
||||
BIN
src/dk/itu/mario/engine/sonar/.DS_Store
vendored
Normal file
BIN
src/dk/itu/mario/engine/sonar/.DS_Store
vendored
Normal file
Binary file not shown.
38
src/dk/itu/mario/engine/sonar/FakeSoundEngine.java
Normal file
38
src/dk/itu/mario/engine/sonar/FakeSoundEngine.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package dk.itu.mario.engine.sonar;
|
||||
|
||||
|
||||
|
||||
import dk.itu.mario.engine.sonar.sample.SonarSample;
|
||||
|
||||
|
||||
public class FakeSoundEngine extends SonarSoundEngine
|
||||
{
|
||||
public void setListener(SoundListener soundListener)
|
||||
{
|
||||
}
|
||||
|
||||
public void shutDown()
|
||||
{
|
||||
}
|
||||
|
||||
public SonarSample loadSample(String resourceName)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void play(SonarSample sample, SoundSource soundSource, float volume, float priority, float rate)
|
||||
{
|
||||
}
|
||||
|
||||
public void clientTick(float alpha)
|
||||
{
|
||||
}
|
||||
|
||||
public void tick()
|
||||
{
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
}
|
||||
}
|
||||
33
src/dk/itu/mario/engine/sonar/FixedSoundSource.java
Normal file
33
src/dk/itu/mario/engine/sonar/FixedSoundSource.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package dk.itu.mario.engine.sonar;
|
||||
|
||||
|
||||
/**
|
||||
* @author Administrator
|
||||
*/
|
||||
public class FixedSoundSource implements SoundSource
|
||||
{
|
||||
private float x;
|
||||
private float y;
|
||||
|
||||
public FixedSoundSource(float x, float y)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public FixedSoundSource(SoundSource soundSource)
|
||||
{
|
||||
this.x = soundSource.getX(1);
|
||||
this.y = soundSource.getY(1);
|
||||
}
|
||||
|
||||
public float getX(float alpha)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
public float getY(float alpha)
|
||||
{
|
||||
return y;
|
||||
}
|
||||
}
|
||||
145
src/dk/itu/mario/engine/sonar/SonarSoundEngine.java
Normal file
145
src/dk/itu/mario/engine/sonar/SonarSoundEngine.java
Normal file
@@ -0,0 +1,145 @@
|
||||
package dk.itu.mario.engine.sonar;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import javax.sound.sampled.*;
|
||||
|
||||
|
||||
import dk.itu.mario.engine.sonar.mixer.ListenerMixer;
|
||||
|
||||
import dk.itu.mario.engine.sonar.sample.SamplePlayer;
|
||||
import dk.itu.mario.engine.sonar.sample.SonarSample;
|
||||
import dk.itu.mario.engine.sonar.sample.SampleLoader;
|
||||
|
||||
|
||||
|
||||
public class SonarSoundEngine implements Runnable
|
||||
{
|
||||
private SonarSample silentSample;
|
||||
private SourceDataLine sdl;
|
||||
private int rate = 44100;
|
||||
private ListenerMixer listenerMixer;
|
||||
private int bufferSize = rate / 100; // 10 ms
|
||||
private ByteBuffer soundBuffer = ByteBuffer.allocate(bufferSize * 4);
|
||||
private float[] leftBuf, rightBuf;
|
||||
private float amplitude = 1;
|
||||
private float targetAmplitude = 1;
|
||||
private boolean alive = true;
|
||||
|
||||
protected SonarSoundEngine()
|
||||
{
|
||||
}
|
||||
|
||||
public SonarSoundEngine(int maxChannels) throws LineUnavailableException
|
||||
{
|
||||
silentSample = new SonarSample(new float[] {0}, 44100);
|
||||
Mixer mixer = AudioSystem.getMixer(null);
|
||||
|
||||
sdl = (SourceDataLine) mixer.getLine(new Line.Info(SourceDataLine.class));
|
||||
sdl.open(new AudioFormat(rate, 16, 2, true, false), bufferSize * 2 * 2 * 2 * 2 * 2);
|
||||
soundBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||
sdl.start();
|
||||
|
||||
try
|
||||
{
|
||||
/* FloatControl volumeControl = (FloatControl) sdl.getControl(FloatControl.Type.MASTER_GAIN);
|
||||
volumeControl.setValue(volumeControl.getMaximum());*/
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
System.out.println("Failed to set the sound volume");
|
||||
}
|
||||
|
||||
listenerMixer = new ListenerMixer(maxChannels);
|
||||
|
||||
leftBuf = new float[bufferSize];
|
||||
rightBuf = new float[bufferSize];
|
||||
|
||||
Thread thread = new Thread(this);
|
||||
thread.setDaemon(true);
|
||||
thread.setPriority(10);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
public void setListener(SoundListener soundListener)
|
||||
{
|
||||
listenerMixer.setSoundListener(soundListener);
|
||||
}
|
||||
|
||||
public void shutDown()
|
||||
{
|
||||
alive = false;
|
||||
}
|
||||
|
||||
public SonarSample loadSample(String resourceName)
|
||||
{
|
||||
try
|
||||
{
|
||||
return SampleLoader.loadSample(resourceName);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.out.println("Failed to load sample " + resourceName + ". Using silent sample");
|
||||
e.printStackTrace();
|
||||
return silentSample;
|
||||
}
|
||||
}
|
||||
|
||||
public void play(SonarSample sample, SoundSource soundSource, float volume, float priority, float rate)
|
||||
{
|
||||
synchronized (listenerMixer)
|
||||
{
|
||||
if(!dk.itu.mario.engine.Art.mute)
|
||||
listenerMixer.addSoundProducer(new SamplePlayer((SonarSample) sample, rate), soundSource, volume, priority);
|
||||
}
|
||||
}
|
||||
|
||||
public void clientTick(float alpha)
|
||||
{
|
||||
synchronized (listenerMixer)
|
||||
{
|
||||
listenerMixer.update(alpha);
|
||||
}
|
||||
}
|
||||
|
||||
public void tick()
|
||||
{
|
||||
soundBuffer.clear();
|
||||
|
||||
// targetAmplitude = (targetAmplitude - 1) * 0.9f + 1;
|
||||
// targetAmplitude = (targetAmplitude - 1) * 0.9f + 1;
|
||||
synchronized (listenerMixer)
|
||||
{
|
||||
float maxAmplitude = listenerMixer.read(leftBuf, rightBuf, rate);
|
||||
// if (maxAmplitude > targetAmplitude) targetAmplitude = maxAmplitude;
|
||||
}
|
||||
|
||||
soundBuffer.clear();
|
||||
float gain = 32000;
|
||||
for (int i = 0; i < bufferSize; i++)
|
||||
{
|
||||
// amplitude += (targetAmplitude - amplitude) / rate;
|
||||
// amplitude = 1;
|
||||
// float gain = 30000;
|
||||
int l = (int) (leftBuf[i] * gain);
|
||||
int r = (int) (rightBuf[i] * gain);
|
||||
if (l > 32767) l = 32767;
|
||||
if (r > 32767) r = 32767;
|
||||
if (l < -32767) l = -32767;
|
||||
if (r < -32767) r = -32767;
|
||||
soundBuffer.putShort((short)l);
|
||||
soundBuffer.putShort((short)r);
|
||||
}
|
||||
|
||||
sdl.write(soundBuffer.array(), 0, bufferSize * 2 * 2);
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
while (alive)
|
||||
{
|
||||
tick();
|
||||
}
|
||||
}
|
||||
}
|
||||
6
src/dk/itu/mario/engine/sonar/SoundListener.java
Normal file
6
src/dk/itu/mario/engine/sonar/SoundListener.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package dk.itu.mario.engine.sonar;
|
||||
|
||||
|
||||
public interface SoundListener extends SoundSource
|
||||
{
|
||||
}
|
||||
8
src/dk/itu/mario/engine/sonar/SoundProducer.java
Normal file
8
src/dk/itu/mario/engine/sonar/SoundProducer.java
Normal file
@@ -0,0 +1,8 @@
|
||||
package dk.itu.mario.engine.sonar;
|
||||
|
||||
public interface SoundProducer
|
||||
{
|
||||
public float read(float[] buf, int readRate);
|
||||
public void skip(int samplesToSkip, int readRate);
|
||||
public boolean isLive();
|
||||
}
|
||||
7
src/dk/itu/mario/engine/sonar/SoundSource.java
Normal file
7
src/dk/itu/mario/engine/sonar/SoundSource.java
Normal file
@@ -0,0 +1,7 @@
|
||||
package dk.itu.mario.engine.sonar;
|
||||
|
||||
public interface SoundSource
|
||||
{
|
||||
public float getX(float alpha);
|
||||
public float getY(float alpha);
|
||||
}
|
||||
7
src/dk/itu/mario/engine/sonar/StereoSoundProducer.java
Normal file
7
src/dk/itu/mario/engine/sonar/StereoSoundProducer.java
Normal file
@@ -0,0 +1,7 @@
|
||||
package dk.itu.mario.engine.sonar;
|
||||
|
||||
public interface StereoSoundProducer
|
||||
{
|
||||
public float read(float[] leftBuf, float[] rightBuf, int readRate);
|
||||
public void skip(int samplesToSkip, int readRate);
|
||||
}
|
||||
BIN
src/dk/itu/mario/engine/sonar/mixer/.DS_Store
vendored
Normal file
BIN
src/dk/itu/mario/engine/sonar/mixer/.DS_Store
vendored
Normal file
Binary file not shown.
93
src/dk/itu/mario/engine/sonar/mixer/ListenerMixer.java
Normal file
93
src/dk/itu/mario/engine/sonar/mixer/ListenerMixer.java
Normal file
@@ -0,0 +1,93 @@
|
||||
package dk.itu.mario.engine.sonar.mixer;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
|
||||
import dk.itu.mario.engine.sonar.SoundListener;
|
||||
import dk.itu.mario.engine.sonar.SoundProducer;
|
||||
import dk.itu.mario.engine.sonar.SoundSource;
|
||||
import dk.itu.mario.engine.sonar.StereoSoundProducer;
|
||||
|
||||
public class ListenerMixer implements StereoSoundProducer
|
||||
{
|
||||
private List<Sound> sounds = new ArrayList<Sound>();
|
||||
private float[] buf = new float[0];
|
||||
private int maxChannels;
|
||||
private SoundListener soundListener;
|
||||
|
||||
public ListenerMixer(int maxChannels)
|
||||
{
|
||||
this.maxChannels = maxChannels;
|
||||
}
|
||||
|
||||
public void setSoundListener(SoundListener soundListener)
|
||||
{
|
||||
this.soundListener = soundListener;
|
||||
}
|
||||
|
||||
public void addSoundProducer(SoundProducer producer, SoundSource soundSource, float volume, float priority)
|
||||
{
|
||||
sounds.add(new Sound(producer, soundSource, volume, priority));
|
||||
}
|
||||
|
||||
public void update(float alpha)
|
||||
{
|
||||
for (Iterator it = sounds.iterator(); it.hasNext();)
|
||||
{
|
||||
Sound sound = (Sound) it.next();
|
||||
sound.update(soundListener, alpha);
|
||||
if (!sound.isLive())
|
||||
{
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public float read(float[] leftBuf, float[] rightBuf, int readRate)
|
||||
{
|
||||
if (buf.length != leftBuf.length) buf = new float[leftBuf.length];
|
||||
|
||||
if (sounds.size() > maxChannels)
|
||||
{
|
||||
Collections.sort(sounds);
|
||||
}
|
||||
|
||||
Arrays.fill(leftBuf, 0);
|
||||
Arrays.fill(rightBuf, 0);
|
||||
float maxAmplitude = 0;
|
||||
for (int i = 0; i < sounds.size(); i++)
|
||||
{
|
||||
Sound sound = (Sound) sounds.get(i);
|
||||
if (i < maxChannels)
|
||||
{
|
||||
sound.read(buf, readRate);
|
||||
float rp = (sound.pan<0?1:1-sound.pan)*sound.amplitude;
|
||||
float lp = (sound.pan>0?1:1+sound.pan)*sound.amplitude;
|
||||
for (int j = 0; j < leftBuf.length; j++)
|
||||
{
|
||||
leftBuf[j] += buf[j]*lp;
|
||||
rightBuf[j] += buf[j]*rp;
|
||||
if (leftBuf[j]>maxAmplitude) maxAmplitude = leftBuf[j];
|
||||
if (rightBuf[j]>maxAmplitude) maxAmplitude = rightBuf[j];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sound.skip(leftBuf.length, readRate);
|
||||
}
|
||||
}
|
||||
|
||||
return maxAmplitude;
|
||||
}
|
||||
|
||||
public void skip(int samplesToSkip, int readRate)
|
||||
{
|
||||
for (int i = 0; i < sounds.size(); i++)
|
||||
{
|
||||
Sound sound = (Sound) sounds.get(i);
|
||||
sound.skip(samplesToSkip, readRate);
|
||||
}
|
||||
}
|
||||
}
|
||||
84
src/dk/itu/mario/engine/sonar/mixer/Sound.java
Normal file
84
src/dk/itu/mario/engine/sonar/mixer/Sound.java
Normal file
@@ -0,0 +1,84 @@
|
||||
package dk.itu.mario.engine.sonar.mixer;
|
||||
|
||||
|
||||
|
||||
import dk.itu.mario.engine.sonar.SoundListener;
|
||||
import dk.itu.mario.engine.sonar.SoundProducer;
|
||||
import dk.itu.mario.engine.sonar.SoundSource;
|
||||
|
||||
|
||||
public class Sound implements Comparable
|
||||
{
|
||||
private static final double l10 = Math.log(10);
|
||||
|
||||
private SoundProducer producer;
|
||||
private SoundSource source;
|
||||
private float volume;
|
||||
private float priority;
|
||||
|
||||
private float x, y, z;
|
||||
private float score = 0;
|
||||
|
||||
public float pan;
|
||||
public float amplitude;
|
||||
|
||||
public Sound(SoundProducer producer, SoundSource source, float volume, float priority)
|
||||
{
|
||||
this.producer = producer;
|
||||
this.source = source;
|
||||
this.volume = volume;
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
public void update(SoundListener listener, float alpha)
|
||||
{
|
||||
x = source.getX(alpha)-listener.getX(alpha);
|
||||
y = source.getY(alpha)-listener.getY(alpha);
|
||||
|
||||
float distSqr = x*x+y*y+z*z;
|
||||
float dist = (float)Math.sqrt(distSqr);
|
||||
|
||||
float REFERENCE_DISTANCE = 1;
|
||||
float ROLLOFF_FACTOR = 2;
|
||||
|
||||
// float dB = (float)(volume + (20 * (Math.log(1.0 / distSqr) / l10)));
|
||||
float dB = (float)(volume - 20*Math.log(1 + ROLLOFF_FACTOR*(dist-REFERENCE_DISTANCE)/REFERENCE_DISTANCE )/ l10);
|
||||
dB = Math.min(dB, +6);
|
||||
// dB = Math.max(dB, MIN_GAIN);
|
||||
|
||||
score = dB*priority;
|
||||
|
||||
// double angle = WMath.atan2(y, x);
|
||||
|
||||
float p = -x/320.0f;
|
||||
if (p<-1) p = -1;
|
||||
if (p>1) p = 1;
|
||||
float dd = distSqr/16;
|
||||
if (dd>1) dd = 1;
|
||||
pan =(p*dd);
|
||||
amplitude = volume*1f;
|
||||
}
|
||||
|
||||
public void read(float[] buf, int readRate)
|
||||
{
|
||||
producer.read(buf, readRate);
|
||||
}
|
||||
|
||||
public void skip(int samplesToSkip, int readRate)
|
||||
{
|
||||
producer.skip(samplesToSkip, readRate);
|
||||
}
|
||||
|
||||
public boolean isLive()
|
||||
{
|
||||
return producer.isLive();
|
||||
}
|
||||
|
||||
public int compareTo(Object o)
|
||||
{
|
||||
Sound s = (Sound)o;
|
||||
if (s.score>score) return 1;
|
||||
if (s.score<score) return -1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
BIN
src/dk/itu/mario/engine/sonar/sample/.DS_Store
vendored
Normal file
BIN
src/dk/itu/mario/engine/sonar/sample/.DS_Store
vendored
Normal file
Binary file not shown.
114
src/dk/itu/mario/engine/sonar/sample/SampleLoader.java
Normal file
114
src/dk/itu/mario/engine/sonar/sample/SampleLoader.java
Normal file
@@ -0,0 +1,114 @@
|
||||
package dk.itu.mario.engine.sonar.sample;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
import javax.sound.sampled.AudioInputStream;
|
||||
import javax.sound.sampled.AudioSystem;
|
||||
import javax.sound.sampled.UnsupportedAudioFileException;
|
||||
|
||||
public class SampleLoader
|
||||
{
|
||||
/**
|
||||
* Loads a sample from an url
|
||||
*/
|
||||
public static SonarSample loadSample(String resourceName) throws UnsupportedAudioFileException, IOException
|
||||
{
|
||||
// Hack to prevent "mark/reset not supported" on some systems
|
||||
InputStream in=SampleLoader.class.getResourceAsStream(resourceName);
|
||||
byte[] d = rip(in);
|
||||
AudioInputStream ais = AudioSystem.getAudioInputStream(new ByteArrayInputStream(d));
|
||||
return buildSample(rip(ais), ais.getFormat());
|
||||
}
|
||||
|
||||
/**
|
||||
* Rips the entire contents of an inputstream into a byte array
|
||||
*/
|
||||
private static byte[] rip(InputStream in) throws IOException
|
||||
{
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
byte[] b = new byte[4096];
|
||||
|
||||
int read = 0;
|
||||
while ((read = in.read(b)) > 0)
|
||||
{
|
||||
bos.write(b, 0, read);
|
||||
}
|
||||
|
||||
bos.close();
|
||||
return bos.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reorganizes audio sample data into the intenal sonar format
|
||||
*/
|
||||
private static SonarSample buildSample(byte[] b, AudioFormat af) throws UnsupportedAudioFileException
|
||||
{
|
||||
// Rip audioformat data
|
||||
int channels = af.getChannels();
|
||||
int sampleSize = af.getSampleSizeInBits();
|
||||
float rate = af.getFrameRate();
|
||||
boolean signed = af.getEncoding() == AudioFormat.Encoding.PCM_SIGNED;
|
||||
|
||||
// Sanity checking
|
||||
if (channels != 1) throw new UnsupportedAudioFileException("Only mono samples are supported");
|
||||
if (!(sampleSize == 8 || sampleSize == 16 || sampleSize == 32)) throw new UnsupportedAudioFileException("Unsupported sample size");
|
||||
if (!(af.getEncoding() == AudioFormat.Encoding.PCM_UNSIGNED || af.getEncoding() == AudioFormat.Encoding.PCM_SIGNED)) throw new UnsupportedAudioFileException("Unsupported encoding");
|
||||
|
||||
// Wrap the data into a bytebuffer, and set up the byte order
|
||||
ByteBuffer bb = ByteBuffer.wrap(b);
|
||||
bb.order(af.isBigEndian() ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
int s = b.length / (sampleSize / 8);
|
||||
float[] buf = new float[s];
|
||||
// Six different cases for reordering the data. Can this be improved without slowing it down?
|
||||
if (sampleSize == 8)
|
||||
{
|
||||
if (signed)
|
||||
{
|
||||
for (int i = 0; i < s; i++)
|
||||
buf[i] = bb.get() / (float)0x80;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < s; i++)
|
||||
buf[i] = ((bb.get()&0xFF)-0x80) / (float)0x80;
|
||||
}
|
||||
}
|
||||
else if (sampleSize == 16)
|
||||
{
|
||||
if (signed)
|
||||
{
|
||||
for (int i = 0; i < s; i++)
|
||||
buf[i] = bb.getShort() / (float)0x8000;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < s; i++)
|
||||
buf[i] = ((bb.getShort()&0xFFFF)-0x8000) / (float)0x8000;
|
||||
}
|
||||
}
|
||||
else if (sampleSize == 32)
|
||||
{
|
||||
if (signed)
|
||||
{
|
||||
for (int i = 0; i < s; i++)
|
||||
buf[i] = bb.getInt() / (float)0x80000000;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Nasty.. check this.
|
||||
for (int i = 0; i < s; i++)
|
||||
buf[i] = ((bb.getInt()&0xFFFFFFFFl)-0x80000000l) / (float)0x80000000;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the completed sample
|
||||
return new SonarSample(buf, rate);
|
||||
}
|
||||
}
|
||||
57
src/dk/itu/mario/engine/sonar/sample/SamplePlayer.java
Normal file
57
src/dk/itu/mario/engine/sonar/sample/SamplePlayer.java
Normal file
@@ -0,0 +1,57 @@
|
||||
package dk.itu.mario.engine.sonar.sample;
|
||||
|
||||
|
||||
|
||||
import dk.itu.mario.engine.sonar.SoundProducer;
|
||||
|
||||
|
||||
public class SamplePlayer implements SoundProducer
|
||||
{
|
||||
private SonarSample sample;
|
||||
private float pos = 0;
|
||||
public boolean alive = true;
|
||||
private float rate;
|
||||
|
||||
public SamplePlayer(SonarSample sample, float rate)
|
||||
{
|
||||
this.rate = rate;
|
||||
this.sample = sample;
|
||||
}
|
||||
|
||||
public float read(float[] buf, int readRate)
|
||||
{
|
||||
float step = (sample.rate*rate)/readRate;
|
||||
|
||||
for (int i=0; i<buf.length; i++)
|
||||
{
|
||||
if (pos>=sample.buf.length)
|
||||
{
|
||||
buf[i] = 0;
|
||||
alive = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[i]=sample.buf[(int)(pos)];
|
||||
}
|
||||
pos+=step;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
public void skip(int samplesToSkip, int readRate)
|
||||
{
|
||||
float step = sample.rate/readRate;
|
||||
pos+=step*samplesToSkip;
|
||||
|
||||
if (pos>=sample.buf.length)
|
||||
{
|
||||
alive = false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isLive()
|
||||
{
|
||||
return alive;
|
||||
}
|
||||
}
|
||||
13
src/dk/itu/mario/engine/sonar/sample/SonarSample.java
Normal file
13
src/dk/itu/mario/engine/sonar/sample/SonarSample.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package dk.itu.mario.engine.sonar.sample;
|
||||
|
||||
public class SonarSample
|
||||
{
|
||||
public final float[] buf;
|
||||
public final float rate;
|
||||
|
||||
public SonarSample(float[] buf, float rate)
|
||||
{
|
||||
this.buf = buf;
|
||||
this.rate = rate;
|
||||
}
|
||||
}
|
||||
BIN
src/dk/itu/mario/engine/sprites/.DS_Store
vendored
Normal file
BIN
src/dk/itu/mario/engine/sprites/.DS_Store
vendored
Normal file
Binary file not shown.
152
src/dk/itu/mario/engine/sprites/BulletBill.java
Normal file
152
src/dk/itu/mario/engine/sprites/BulletBill.java
Normal file
@@ -0,0 +1,152 @@
|
||||
package dk.itu.mario.engine.sprites;
|
||||
|
||||
|
||||
import dk.itu.mario.engine.Art;
|
||||
import dk.itu.mario.scene.LevelScene;
|
||||
|
||||
|
||||
public class BulletBill extends Sprite
|
||||
{
|
||||
private int width = 4;
|
||||
int height = 24;
|
||||
|
||||
private LevelScene world;
|
||||
public int facing;
|
||||
|
||||
public boolean avoidCliffs = false;
|
||||
public int anim;
|
||||
|
||||
public boolean dead = false;
|
||||
private int deadTime = 0;
|
||||
|
||||
|
||||
public BulletBill(LevelScene world, float x, float y, int dir)
|
||||
{
|
||||
sheet = Art.enemies;
|
||||
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.world = world;
|
||||
xPicO = 8;
|
||||
yPicO = 31;
|
||||
|
||||
height = 12;
|
||||
facing = 0;
|
||||
wPic = 16;
|
||||
yPic = 5;
|
||||
|
||||
xPic = 0;
|
||||
ya = -5;
|
||||
this.facing = dir;
|
||||
}
|
||||
|
||||
public void collideCheck()
|
||||
{
|
||||
if (dead) return;
|
||||
|
||||
float xMarioD = world.mario.x - x;
|
||||
float yMarioD = world.mario.y - y;
|
||||
float w = 16;
|
||||
if (xMarioD > -16 && xMarioD < 16)
|
||||
{
|
||||
if (yMarioD > -height && yMarioD < world.mario.height)
|
||||
{
|
||||
if (world.mario.ya > 0 && yMarioD <= 0 && (!world.mario.onGround || !world.mario.wasOnGround))
|
||||
{
|
||||
world.mario.stomp(this);
|
||||
dead = true;
|
||||
|
||||
xa = 0;
|
||||
ya = 1;
|
||||
deadTime = 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
world.mario.getHurt(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void move()
|
||||
{
|
||||
if (deadTime > 0)
|
||||
{
|
||||
deadTime--;
|
||||
|
||||
if (deadTime == 0)
|
||||
{
|
||||
deadTime = 1;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
world.addSprite(new Sparkle((int) (x + Math.random() * 16 - 8) + 4, (int) (y - Math.random() * 8) + 4, (float) (Math.random() * 2 - 1), (float) Math.random() * -1, 0, 1, 5));
|
||||
}
|
||||
spriteContext.removeSprite(this);
|
||||
}
|
||||
|
||||
x += xa;
|
||||
y += ya;
|
||||
ya *= 0.95;
|
||||
ya += 1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
float sideWaysSpeed = 4f;
|
||||
|
||||
xa = facing * sideWaysSpeed;
|
||||
xFlipPic = facing == -1;
|
||||
move(xa, 0);
|
||||
}
|
||||
|
||||
private boolean move(float xa, float ya)
|
||||
{
|
||||
x += xa;
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean fireballCollideCheck(Fireball fireball)
|
||||
{
|
||||
if (deadTime != 0) return false;
|
||||
|
||||
float xD = fireball.x - x;
|
||||
float yD = fireball.y - y;
|
||||
|
||||
if (xD > -16 && xD < 16)
|
||||
{
|
||||
if (yD > -height && yD < fireball.height)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shellCollideCheck(Shell shell)
|
||||
{
|
||||
if (deadTime != 0) return false;
|
||||
|
||||
float xD = shell.x - x;
|
||||
float yD = shell.y - y;
|
||||
|
||||
if (xD > -16 && xD < 16)
|
||||
{
|
||||
if (yD > -height && yD < shell.height)
|
||||
{
|
||||
world.sound.play(Art.samples[Art.SAMPLE_MARIO_KICK], this, 1, 1, 1);
|
||||
|
||||
dead = true;
|
||||
|
||||
xa = 0;
|
||||
ya = 1;
|
||||
deadTime = 100;
|
||||
|
||||
if(world.recorder != null)
|
||||
world.recorder.shellKillRecord(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
41
src/dk/itu/mario/engine/sprites/CoinAnim.java
Normal file
41
src/dk/itu/mario/engine/sprites/CoinAnim.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package dk.itu.mario.engine.sprites;
|
||||
|
||||
import dk.itu.mario.engine.Art;
|
||||
import dk.itu.mario.level.Level;
|
||||
|
||||
|
||||
|
||||
public class CoinAnim extends Sprite
|
||||
{
|
||||
private int life = 10;
|
||||
|
||||
public CoinAnim(int xTile, int yTile)
|
||||
{
|
||||
sheet = Art.level;
|
||||
wPic = hPic = 16;
|
||||
|
||||
x = xTile * 16;
|
||||
y = yTile * 16 - 16;
|
||||
xa = 0;
|
||||
ya = -6f;
|
||||
xPic = 0;
|
||||
yPic = 2;
|
||||
}
|
||||
|
||||
public void move()
|
||||
{
|
||||
if (life-- < 0)
|
||||
{
|
||||
Sprite.spriteContext.removeSprite(this);
|
||||
for (int xx = 0; xx < 2; xx++)
|
||||
for (int yy = 0; yy < 2; yy++)
|
||||
Sprite.spriteContext.addSprite(new Sparkle((int)x + xx * 8 + (int) (Math.random() * 8), (int)y + yy * 8 + (int) (Math.random() * 8), 0, 0, 0, 2, 5));
|
||||
}
|
||||
|
||||
xPic = life & 3;
|
||||
|
||||
x += xa;
|
||||
y += ya;
|
||||
ya += 1;
|
||||
}
|
||||
}
|
||||
443
src/dk/itu/mario/engine/sprites/Enemy.java
Normal file
443
src/dk/itu/mario/engine/sprites/Enemy.java
Normal file
@@ -0,0 +1,443 @@
|
||||
package dk.itu.mario.engine.sprites;
|
||||
|
||||
import java.awt.Graphics;
|
||||
|
||||
|
||||
import dk.itu.mario.engine.Art;
|
||||
import dk.itu.mario.level.Level;
|
||||
import dk.itu.mario.scene.LevelScene;
|
||||
|
||||
|
||||
|
||||
public class Enemy extends Sprite
|
||||
{
|
||||
public static final int ENEMY_RED_KOOPA = 0;
|
||||
public static final int ENEMY_GREEN_KOOPA = 1;
|
||||
public static final int ENEMY_GOOMBA = 2;
|
||||
public static final int ENEMY_SPIKY = 3;
|
||||
public static final int ENEMY_FLOWER = 4;
|
||||
|
||||
private static float GROUND_INERTIA = 0.89f;
|
||||
private static float AIR_INERTIA = 0.89f;
|
||||
|
||||
private float runTime;
|
||||
private boolean onGround = false;
|
||||
private boolean mayJump = false;
|
||||
private int jumpTime = 0;
|
||||
private float xJumpSpeed;
|
||||
private float yJumpSpeed;
|
||||
|
||||
int width = 4;
|
||||
int height = 24;
|
||||
|
||||
private LevelScene world;
|
||||
public int facing;
|
||||
public int deadTime = 0;
|
||||
public boolean flyDeath = false;
|
||||
|
||||
public boolean avoidCliffs = true;
|
||||
public int type;
|
||||
|
||||
public boolean winged = true;
|
||||
private int wingTime = 0;
|
||||
|
||||
public boolean noFireballDeath;
|
||||
|
||||
public Enemy(LevelScene world, int x, int y, int dir, int type, boolean winged)
|
||||
{
|
||||
this.type = type;
|
||||
sheet = Art.enemies;
|
||||
this.winged = winged;
|
||||
|
||||
|
||||
this.world = world;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
|
||||
xPicO = 8;
|
||||
yPicO = 31;
|
||||
|
||||
avoidCliffs = type == Enemy.ENEMY_RED_KOOPA;
|
||||
|
||||
noFireballDeath = type == Enemy.ENEMY_SPIKY;
|
||||
|
||||
yPic = type;
|
||||
if (yPic > 1) height = 12;
|
||||
facing = dir;
|
||||
if (facing == 0) facing = 1;
|
||||
this.wPic = 16;
|
||||
}
|
||||
|
||||
public void collideCheck()
|
||||
{
|
||||
if (deadTime != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float xMarioD = world.mario.x - x;
|
||||
float yMarioD = world.mario.y - y;
|
||||
float w = 16;
|
||||
|
||||
//if the distance to mario is within the sprite (in x)
|
||||
if (xMarioD > -width*2-4 && xMarioD < width*2+4)
|
||||
{
|
||||
//if the distance to mario is within the sprite (in y)
|
||||
if (yMarioD > -height && yMarioD < world.mario.height)
|
||||
{
|
||||
if (type != Enemy.ENEMY_SPIKY && world.mario.ya > 0 && yMarioD <= 0 && (!world.mario.onGround || !world.mario.wasOnGround))
|
||||
{
|
||||
world.mario.stomp(this);
|
||||
|
||||
if (winged)
|
||||
{
|
||||
winged = false;
|
||||
ya = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.yPicO = 31 - (32 - 8);
|
||||
hPic = 8;
|
||||
if (spriteTemplate != null) spriteTemplate.isDead = true;
|
||||
deadTime = 10;
|
||||
winged = false;
|
||||
|
||||
if (type == Enemy.ENEMY_RED_KOOPA)
|
||||
{
|
||||
spriteContext.addSprite(new Shell(world, x, y, 0));
|
||||
}
|
||||
else if (type == Enemy.ENEMY_GREEN_KOOPA)
|
||||
{
|
||||
spriteContext.addSprite(new Shell(world, x, y, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
world.mario.getHurt(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void move()
|
||||
{
|
||||
//TODO: some kind of suicide error when one enemy is created
|
||||
if (y > world.level.getHeight() * 16 + 16 && deadTime <= 0)
|
||||
{
|
||||
if(world.recorder != null)
|
||||
world.recorder.killSuicideRecord(this);
|
||||
|
||||
deadTime = 1;
|
||||
}
|
||||
|
||||
wingTime++;
|
||||
if (deadTime > 0)
|
||||
{
|
||||
deadTime--;
|
||||
|
||||
if (deadTime == 0)
|
||||
{
|
||||
deadTime = 1;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
world.addSprite(new Sparkle((int) (x + Math.random() * 16 - 8) + 4, (int) (y - Math.random() * 8) + 4, (float) (Math.random() * 2 - 1), (float) Math.random() * -1, 0, 1, 5));
|
||||
}
|
||||
spriteContext.removeSprite(this);
|
||||
}
|
||||
|
||||
if (flyDeath)
|
||||
{
|
||||
x += xa;
|
||||
y += ya;
|
||||
ya *= 0.95;
|
||||
ya += 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
float sideWaysSpeed = 1.75f;
|
||||
// float sideWaysSpeed = onGround ? 2.5f : 1.2f;
|
||||
|
||||
if (xa > 2)
|
||||
{
|
||||
facing = 1;
|
||||
}
|
||||
if (xa < -2)
|
||||
{
|
||||
facing = -1;
|
||||
}
|
||||
|
||||
xa = facing * sideWaysSpeed;
|
||||
|
||||
mayJump = (onGround);
|
||||
|
||||
xFlipPic = facing == -1;
|
||||
|
||||
runTime += (Math.abs(xa)) + 5;
|
||||
|
||||
int runFrame = ((int) (runTime / 20)) % 2;
|
||||
|
||||
if (!onGround)
|
||||
{
|
||||
runFrame = 1;
|
||||
}
|
||||
|
||||
|
||||
if (!move(xa, 0)) facing = -facing;
|
||||
onGround = false;
|
||||
move(0, ya);
|
||||
|
||||
ya *= winged ? 0.95f : 0.85f;
|
||||
if (onGround)
|
||||
{
|
||||
xa *= GROUND_INERTIA;
|
||||
}
|
||||
else
|
||||
{
|
||||
xa *= AIR_INERTIA;
|
||||
}
|
||||
|
||||
if (!onGround)
|
||||
{
|
||||
if (winged)
|
||||
{
|
||||
ya += 0.6f;
|
||||
}
|
||||
else
|
||||
{
|
||||
ya += 2;
|
||||
}
|
||||
}
|
||||
else if (winged)
|
||||
{
|
||||
ya = -10;
|
||||
}
|
||||
|
||||
if (winged) runFrame = wingTime / 4 % 2;
|
||||
|
||||
xPic = runFrame;
|
||||
}
|
||||
|
||||
private boolean move(float xa, float ya)
|
||||
{
|
||||
while (xa > 8)
|
||||
{
|
||||
if (!move(8, 0)) return false;
|
||||
xa -= 8;
|
||||
}
|
||||
while (xa < -8)
|
||||
{
|
||||
if (!move(-8, 0)) return false;
|
||||
xa += 8;
|
||||
}
|
||||
while (ya > 8)
|
||||
{
|
||||
if (!move(0, 8)) return false;
|
||||
ya -= 8;
|
||||
}
|
||||
while (ya < -8)
|
||||
{
|
||||
if (!move(0, -8)) return false;
|
||||
ya += 8;
|
||||
}
|
||||
|
||||
boolean collide = false;
|
||||
if (ya > 0)
|
||||
{
|
||||
if (isBlocking(x + xa - width, y + ya, xa, 0)) collide = true;
|
||||
else if (isBlocking(x + xa + width, y + ya, xa, 0)) collide = true;
|
||||
else if (isBlocking(x + xa - width, y + ya + 1, xa, ya)) collide = true;
|
||||
else if (isBlocking(x + xa + width, y + ya + 1, xa, ya)) collide = true;
|
||||
}
|
||||
if (ya < 0)
|
||||
{
|
||||
if (isBlocking(x + xa, y + ya - height, xa, ya)) collide = true;
|
||||
else if (collide || isBlocking(x + xa - width, y + ya - height, xa, ya)) collide = true;
|
||||
else if (collide || isBlocking(x + xa + width, y + ya - height, xa, ya)) collide = true;
|
||||
}
|
||||
if (xa > 0)
|
||||
{
|
||||
if (isBlocking(x + xa + width, y + ya - height, xa, ya)) collide = true;
|
||||
if (isBlocking(x + xa + width, y + ya - height / 2, xa, ya)) collide = true;
|
||||
if (isBlocking(x + xa + width, y + ya, xa, ya)) collide = true;
|
||||
|
||||
if (avoidCliffs && onGround && !world.level.isBlocking((int) ((x + xa + width) / 16), (int) ((y) / 16 + 1), xa, 1)) collide = true;
|
||||
}
|
||||
if (xa < 0)
|
||||
{
|
||||
if (isBlocking(x + xa - width, y + ya - height, xa, ya)) collide = true;
|
||||
if (isBlocking(x + xa - width, y + ya - height / 2, xa, ya)) collide = true;
|
||||
if (isBlocking(x + xa - width, y + ya, xa, ya)) collide = true;
|
||||
|
||||
if (avoidCliffs && onGround && !world.level.isBlocking((int) ((x + xa - width) / 16), (int) ((y) / 16 + 1), xa, 1)) collide = true;
|
||||
}
|
||||
|
||||
if (collide)
|
||||
{
|
||||
if (xa < 0)
|
||||
{
|
||||
x = (int) ((x - width) / 16) * 16 + width;
|
||||
this.xa = 0;
|
||||
}
|
||||
if (xa > 0)
|
||||
{
|
||||
x = (int) ((x + width) / 16 + 1) * 16 - width - 1;
|
||||
this.xa = 0;
|
||||
}
|
||||
if (ya < 0)
|
||||
{
|
||||
y = (int) ((y - height) / 16) * 16 + height;
|
||||
jumpTime = 0;
|
||||
this.ya = 0;
|
||||
}
|
||||
if (ya > 0)
|
||||
{
|
||||
y = (int) (y / 16 + 1) * 16 - 1;
|
||||
onGround = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
x += xa;
|
||||
y += ya;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBlocking(float _x, float _y, float xa, float ya)
|
||||
{
|
||||
int x = (int) (_x / 16);
|
||||
int y = (int) (_y / 16);
|
||||
if (x == (int) (this.x / 16) && y == (int) (this.y / 16)) return false;
|
||||
|
||||
boolean blocking = world.level.isBlocking(x, y, xa, ya);
|
||||
|
||||
byte block = world.level.getBlock(x, y);
|
||||
|
||||
return blocking;
|
||||
}
|
||||
|
||||
public boolean shellCollideCheck(Shell shell)
|
||||
{
|
||||
if (deadTime != 0) return false;
|
||||
|
||||
float xD = shell.x - x;
|
||||
float yD = shell.y - y;
|
||||
|
||||
if (xD > -16 && xD < 16)
|
||||
{
|
||||
if (yD > -height && yD < shell.height)
|
||||
{
|
||||
world.sound.play(Art.samples[Art.SAMPLE_MARIO_KICK], this, 1, 1, 1);
|
||||
|
||||
xa = shell.facing * 2;
|
||||
ya = -5;
|
||||
flyDeath = true;
|
||||
if (spriteTemplate != null) spriteTemplate.isDead = true;
|
||||
deadTime = 100;
|
||||
winged = false;
|
||||
hPic = -hPic;
|
||||
yPicO = -yPicO + 16;
|
||||
|
||||
if(world.recorder != null)
|
||||
world.recorder.shellKillRecord(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean fireballCollideCheck(Fireball fireball)
|
||||
{
|
||||
if (deadTime != 0) return false;
|
||||
|
||||
float xD = fireball.x - x;
|
||||
float yD = fireball.y - y;
|
||||
|
||||
if (xD > -16 && xD < 16)
|
||||
{
|
||||
if (yD > -height && yD < fireball.height)
|
||||
{
|
||||
if (noFireballDeath) return true;
|
||||
|
||||
world.sound.play(Art.samples[Art.SAMPLE_MARIO_KICK], this, 1, 1, 1);
|
||||
|
||||
xa = fireball.facing * 2;
|
||||
ya = -5;
|
||||
flyDeath = true;
|
||||
if (spriteTemplate != null) spriteTemplate.isDead = true;
|
||||
deadTime = 100;
|
||||
winged = false;
|
||||
hPic = -hPic;
|
||||
yPicO = -yPicO + 16;
|
||||
|
||||
|
||||
if(world.recorder != null)
|
||||
world.recorder.fireKillRecord(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void bumpCheck(int xTile, int yTile)
|
||||
{
|
||||
if (deadTime != 0) return;
|
||||
|
||||
if (x + width > xTile * 16 && x - width < xTile * 16 + 16 && yTile == (int) ((y - 1) / 16))
|
||||
{
|
||||
world.sound.play(Art.samples[Art.SAMPLE_MARIO_KICK], this, 1, 1, 1);
|
||||
|
||||
xa = -world.mario.facing * 2;
|
||||
ya = -5;
|
||||
flyDeath = true;
|
||||
if (spriteTemplate != null) spriteTemplate.isDead = true;
|
||||
deadTime = 100;
|
||||
winged = false;
|
||||
hPic = -hPic;
|
||||
yPicO = -yPicO + 16;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void render(Graphics og, float alpha)
|
||||
{
|
||||
if (winged)
|
||||
{
|
||||
int xPixel = (int) (xOld + (x - xOld) * alpha) - xPicO;
|
||||
int yPixel = (int) (yOld + (y - yOld) * alpha) - yPicO;
|
||||
|
||||
if (type == Enemy.ENEMY_GREEN_KOOPA || type == Enemy.ENEMY_RED_KOOPA)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
xFlipPic = !xFlipPic;
|
||||
og.drawImage(sheet[wingTime / 4 % 2][4], xPixel + (xFlipPic ? wPic : 0) + (xFlipPic ? 10 : -10), yPixel + (yFlipPic ? hPic : 0) - 8, xFlipPic ? -wPic : wPic, yFlipPic ? -hPic : hPic, null);
|
||||
xFlipPic = !xFlipPic;
|
||||
}
|
||||
}
|
||||
|
||||
super.render(og, alpha);
|
||||
|
||||
if (winged)
|
||||
{
|
||||
int xPixel = (int) (xOld + (x - xOld) * alpha) - xPicO;
|
||||
int yPixel = (int) (yOld + (y - yOld) * alpha) - yPicO;
|
||||
|
||||
if (type == Enemy.ENEMY_GREEN_KOOPA || type == Enemy.ENEMY_RED_KOOPA)
|
||||
{
|
||||
og.drawImage(sheet[wingTime / 4 % 2][4], xPixel + (xFlipPic ? wPic : 0) + (xFlipPic ? 10 : -10), yPixel + (yFlipPic ? hPic : 0) - 10, xFlipPic ? -wPic : wPic, yFlipPic ? -hPic : hPic, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
og.drawImage(sheet[wingTime / 4 % 2][4], xPixel + (xFlipPic ? wPic : 0) + (xFlipPic ? 10 : -10), yPixel + (yFlipPic ? hPic : 0) - 8, xFlipPic ? -wPic : wPic, yFlipPic ? -hPic : hPic, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
63
src/dk/itu/mario/engine/sprites/FireFlower.java
Normal file
63
src/dk/itu/mario/engine/sprites/FireFlower.java
Normal file
@@ -0,0 +1,63 @@
|
||||
package dk.itu.mario.engine.sprites;
|
||||
|
||||
|
||||
import dk.itu.mario.engine.Art;
|
||||
import dk.itu.mario.scene.LevelScene;
|
||||
|
||||
|
||||
|
||||
public class FireFlower extends Sprite
|
||||
{
|
||||
private int width = 4;
|
||||
int height = 24;
|
||||
|
||||
private LevelScene world;
|
||||
public int facing;
|
||||
|
||||
public boolean avoidCliffs = false;
|
||||
private int life;
|
||||
|
||||
public FireFlower(LevelScene world, int x, int y)
|
||||
{
|
||||
sheet = Art.items;
|
||||
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.world = world;
|
||||
xPicO = 8;
|
||||
yPicO = 15;
|
||||
|
||||
xPic = 1;
|
||||
yPic = 0;
|
||||
height = 12;
|
||||
facing = 1;
|
||||
wPic = hPic = 16;
|
||||
life = 0;
|
||||
}
|
||||
|
||||
public void collideCheck()
|
||||
{
|
||||
float xMarioD = world.mario.x - x;
|
||||
float yMarioD = world.mario.y - y;
|
||||
float w = 16;
|
||||
if (xMarioD > -16 && xMarioD < 16)
|
||||
{
|
||||
if (yMarioD > -height && yMarioD < world.mario.height)
|
||||
{
|
||||
world.mario.getFlower();
|
||||
spriteContext.removeSprite(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void move()
|
||||
{
|
||||
if (life<9)
|
||||
{
|
||||
layer = 0;
|
||||
y--;
|
||||
life++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
220
src/dk/itu/mario/engine/sprites/Fireball.java
Normal file
220
src/dk/itu/mario/engine/sprites/Fireball.java
Normal file
@@ -0,0 +1,220 @@
|
||||
package dk.itu.mario.engine.sprites;
|
||||
|
||||
|
||||
import dk.itu.mario.engine.Art;
|
||||
import dk.itu.mario.scene.LevelScene;
|
||||
|
||||
|
||||
|
||||
public class Fireball extends Sprite
|
||||
{
|
||||
private static float GROUND_INERTIA = 0.89f;
|
||||
private static float AIR_INERTIA = 0.89f;
|
||||
|
||||
private float runTime;
|
||||
private boolean onGround = false;
|
||||
|
||||
private int width = 4;
|
||||
int height = 24;
|
||||
|
||||
private LevelScene world;
|
||||
public int facing;
|
||||
|
||||
public boolean avoidCliffs = false;
|
||||
public int anim;
|
||||
|
||||
public boolean dead = false;
|
||||
private int deadTime = 0;
|
||||
|
||||
public Fireball(LevelScene world, float x, float y, int facing)
|
||||
{
|
||||
sheet = Art.particles;
|
||||
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.world = world;
|
||||
xPicO = 4;
|
||||
yPicO = 4;
|
||||
|
||||
yPic = 3;
|
||||
height = 8;
|
||||
this.facing = facing;
|
||||
wPic = 8;
|
||||
hPic = 8;
|
||||
|
||||
xPic = 4;
|
||||
ya = 4;
|
||||
}
|
||||
|
||||
public void move()
|
||||
{
|
||||
if (deadTime > 0)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
world.addSprite(new Sparkle((int) (x + Math.random() * 8 - 4)+4, (int) (y + Math.random() * 8-4)+2, (float) Math.random() * 2 - 1-facing, (float) Math.random() *2 -1, 0, 1, 5));
|
||||
}
|
||||
spriteContext.removeSprite(this);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (facing != 0) anim++;
|
||||
|
||||
float sideWaysSpeed = 8f;
|
||||
// float sideWaysSpeed = onGround ? 2.5f : 1.2f;
|
||||
|
||||
if (xa > 2)
|
||||
{
|
||||
facing = 1;
|
||||
}
|
||||
if (xa < -2)
|
||||
{
|
||||
facing = -1;
|
||||
}
|
||||
|
||||
xa = facing * sideWaysSpeed;
|
||||
|
||||
world.checkFireballCollide(this);
|
||||
|
||||
xFlipPic = facing == -1;
|
||||
|
||||
runTime += (Math.abs(xa)) + 5;
|
||||
|
||||
xPic = (anim) % 4;
|
||||
|
||||
|
||||
|
||||
if (!move(xa, 0))
|
||||
{
|
||||
die();
|
||||
}
|
||||
|
||||
onGround = false;
|
||||
move(0, ya);
|
||||
if (onGround) ya = -10;
|
||||
|
||||
ya *= 0.95f;
|
||||
if (onGround)
|
||||
{
|
||||
xa *= GROUND_INERTIA;
|
||||
}
|
||||
else
|
||||
{
|
||||
xa *= AIR_INERTIA;
|
||||
}
|
||||
|
||||
if (!onGround)
|
||||
{
|
||||
ya += 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean move(float xa, float ya)
|
||||
{
|
||||
while (xa > 8)
|
||||
{
|
||||
if (!move(8, 0)) return false;
|
||||
xa -= 8;
|
||||
}
|
||||
while (xa < -8)
|
||||
{
|
||||
if (!move(-8, 0)) return false;
|
||||
xa += 8;
|
||||
}
|
||||
while (ya > 8)
|
||||
{
|
||||
if (!move(0, 8)) return false;
|
||||
ya -= 8;
|
||||
}
|
||||
while (ya < -8)
|
||||
{
|
||||
if (!move(0, -8)) return false;
|
||||
ya += 8;
|
||||
}
|
||||
|
||||
boolean collide = false;
|
||||
if (ya > 0)
|
||||
{
|
||||
if (isBlocking(x + xa - width, y + ya, xa, 0)) collide = true;
|
||||
else if (isBlocking(x + xa + width, y + ya, xa, 0)) collide = true;
|
||||
else if (isBlocking(x + xa - width, y + ya + 1, xa, ya)) collide = true;
|
||||
else if (isBlocking(x + xa + width, y + ya + 1, xa, ya)) collide = true;
|
||||
}
|
||||
if (ya < 0)
|
||||
{
|
||||
if (isBlocking(x + xa, y + ya - height, xa, ya)) collide = true;
|
||||
else if (collide || isBlocking(x + xa - width, y + ya - height, xa, ya)) collide = true;
|
||||
else if (collide || isBlocking(x + xa + width, y + ya - height, xa, ya)) collide = true;
|
||||
}
|
||||
if (xa > 0)
|
||||
{
|
||||
if (isBlocking(x + xa + width, y + ya - height, xa, ya)) collide = true;
|
||||
if (isBlocking(x + xa + width, y + ya - height / 2, xa, ya)) collide = true;
|
||||
if (isBlocking(x + xa + width, y + ya, xa, ya)) collide = true;
|
||||
|
||||
if (avoidCliffs && onGround && !world.level.isBlocking((int) ((x + xa + width) / 16), (int) ((y) / 16 + 1), xa, 1)) collide = true;
|
||||
}
|
||||
if (xa < 0)
|
||||
{
|
||||
if (isBlocking(x + xa - width, y + ya - height, xa, ya)) collide = true;
|
||||
if (isBlocking(x + xa - width, y + ya - height / 2, xa, ya)) collide = true;
|
||||
if (isBlocking(x + xa - width, y + ya, xa, ya)) collide = true;
|
||||
|
||||
if (avoidCliffs && onGround && !world.level.isBlocking((int) ((x + xa - width) / 16), (int) ((y) / 16 + 1), xa, 1)) collide = true;
|
||||
}
|
||||
|
||||
if (collide)
|
||||
{
|
||||
if (xa < 0)
|
||||
{
|
||||
x = (int) ((x - width) / 16) * 16 + width;
|
||||
this.xa = 0;
|
||||
}
|
||||
if (xa > 0)
|
||||
{
|
||||
x = (int) ((x + width) / 16 + 1) * 16 - width - 1;
|
||||
this.xa = 0;
|
||||
}
|
||||
if (ya < 0)
|
||||
{
|
||||
y = (int) ((y - height) / 16) * 16 + height;
|
||||
this.ya = 0;
|
||||
}
|
||||
if (ya > 0)
|
||||
{
|
||||
y = (int) (y / 16 + 1) * 16 - 1;
|
||||
onGround = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
x += xa;
|
||||
y += ya;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBlocking(float _x, float _y, float xa, float ya)
|
||||
{
|
||||
int x = (int) (_x / 16);
|
||||
int y = (int) (_y / 16);
|
||||
if (x == (int) (this.x / 16) && y == (int) (this.y / 16)) return false;
|
||||
|
||||
boolean blocking = world.level.isBlocking(x, y, xa, ya);
|
||||
|
||||
byte block = world.level.getBlock(x, y);
|
||||
|
||||
return blocking;
|
||||
}
|
||||
|
||||
public void die()
|
||||
{
|
||||
dead = true;
|
||||
|
||||
xa = -facing * 2;
|
||||
ya = -5;
|
||||
deadTime = 100;
|
||||
}
|
||||
}
|
||||
103
src/dk/itu/mario/engine/sprites/FlowerEnemy.java
Normal file
103
src/dk/itu/mario/engine/sprites/FlowerEnemy.java
Normal file
@@ -0,0 +1,103 @@
|
||||
package dk.itu.mario.engine.sprites;
|
||||
|
||||
import dk.itu.mario.level.Level;
|
||||
import dk.itu.mario.scene.LevelScene;
|
||||
import dk.itu.mario.engine.sprites.*;
|
||||
|
||||
public class FlowerEnemy extends Enemy
|
||||
{
|
||||
private int tick;
|
||||
private int yStart;
|
||||
private int jumpTime = 0;
|
||||
private LevelScene world;
|
||||
|
||||
public FlowerEnemy(LevelScene world, int x, int y)
|
||||
{
|
||||
super(world, x, y, 1, ENEMY_SPIKY, false);
|
||||
|
||||
noFireballDeath = false;
|
||||
this.world = world;
|
||||
this.xPic = 0;
|
||||
this.yPic = 6;
|
||||
this.yPicO = 24;
|
||||
this.height = 12;
|
||||
this.width = 2;
|
||||
|
||||
yStart = y;
|
||||
ya = -8;
|
||||
|
||||
this.y-=1;
|
||||
|
||||
this.layer = 0;
|
||||
for (int i=0; i<4; i++)
|
||||
{
|
||||
move();
|
||||
}
|
||||
}
|
||||
|
||||
public void move()
|
||||
{
|
||||
if (deadTime > 0)
|
||||
{
|
||||
deadTime--;
|
||||
|
||||
if (deadTime == 0)
|
||||
{
|
||||
deadTime = 1;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
world.addSprite(new Sparkle((int) (x + Math.random() * 16 - 8) + 4, (int) (y - Math.random() * 8) + 4, (float) (Math.random() * 2 - 1), (float) Math.random() * -1, 0, 1, 5));
|
||||
}
|
||||
spriteContext.removeSprite(this);
|
||||
}
|
||||
|
||||
x += xa;
|
||||
y += ya;
|
||||
ya *= 0.95;
|
||||
ya += 1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
tick++;
|
||||
|
||||
if (y>=yStart)
|
||||
{
|
||||
y = yStart;
|
||||
|
||||
int xd = (int)(Math.abs(world.mario.x-x));
|
||||
jumpTime++;
|
||||
if (jumpTime>40 && xd>24)
|
||||
{
|
||||
ya = -8;
|
||||
}
|
||||
else
|
||||
{
|
||||
ya = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
jumpTime = 0;
|
||||
}
|
||||
|
||||
y+=ya;
|
||||
ya*=0.9;
|
||||
ya+=0.1f;
|
||||
|
||||
xPic = ((tick/2)&1)*2+((tick/6)&1);
|
||||
}
|
||||
|
||||
/* public void render(Graphics og, float alpha)
|
||||
{
|
||||
if (!visible) return;
|
||||
|
||||
int xPixel = (int)(xOld+(x-xOld)*alpha)-xPicO;
|
||||
int yPixel = (int)(yOld+(y-yOld)*alpha)-yPicO;
|
||||
|
||||
int a = ((tick/3)&1)*2;
|
||||
// a += ((tick/8)&1);
|
||||
og.drawImage(sheet[a*2+0][6], xPixel-8, yPixel+8, 16, 32, null);
|
||||
og.drawImage(sheet[a*2+1][6], xPixel+8, yPixel+8, 16, 32, null);
|
||||
}*/
|
||||
}
|
||||
918
src/dk/itu/mario/engine/sprites/Mario.java
Normal file
918
src/dk/itu/mario/engine/sprites/Mario.java
Normal file
@@ -0,0 +1,918 @@
|
||||
package dk.itu.mario.engine.sprites;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
import dk.itu.mario.engine.Art;
|
||||
import dk.itu.mario.engine.DataRecorder;
|
||||
import dk.itu.mario.engine.sonar.FixedSoundSource;
|
||||
import dk.itu.mario.level.Level;
|
||||
import dk.itu.mario.scene.LevelScene;
|
||||
import dk.itu.mario.scene.Scene;
|
||||
|
||||
|
||||
|
||||
|
||||
public class Mario extends Sprite
|
||||
{
|
||||
public static boolean large = false;
|
||||
public static boolean fire = false;
|
||||
public static int coins = 0;
|
||||
public static int lives = 3;
|
||||
public static String levelString = "none";
|
||||
|
||||
public static void resetStatic()
|
||||
{
|
||||
large = false;
|
||||
fire = false;
|
||||
coins = 0;
|
||||
lives = 3;
|
||||
levelString = "none";
|
||||
}
|
||||
|
||||
public static final int KEY_LEFT = 0;
|
||||
public static final int KEY_RIGHT = 1;
|
||||
public static final int KEY_DOWN = 2;
|
||||
public static final int KEY_UP = 3;
|
||||
public static final int KEY_JUMP = 4;
|
||||
public static final int KEY_SPEED = 5;
|
||||
public static final int KEY_ENTER = 6;
|
||||
|
||||
private static float GROUND_INERTIA = 0.89f;
|
||||
private static float AIR_INERTIA = 0.89f;
|
||||
|
||||
public boolean[] keys;
|
||||
private float runTime;
|
||||
boolean wasOnGround = false;
|
||||
boolean onGround = false;
|
||||
private boolean mayJump = false;
|
||||
public boolean ducking = false;
|
||||
public boolean running = false;
|
||||
public int direction = 0;
|
||||
private boolean sliding = false;
|
||||
private int jumpTime = 0;
|
||||
private float xJumpSpeed;
|
||||
private float yJumpSpeed;
|
||||
private boolean canShoot = false;
|
||||
|
||||
int width = 4;
|
||||
int height = 24;
|
||||
|
||||
private LevelScene world;
|
||||
public int facing;
|
||||
private int powerUpTime = 0;
|
||||
|
||||
public int xDeathPos, yDeathPos;
|
||||
|
||||
public int deathTime = 0;
|
||||
public int winTime = 0;
|
||||
private int invulnerableTime = 0;
|
||||
|
||||
public Sprite carried = null;
|
||||
private static Mario instance;
|
||||
|
||||
public Mario(LevelScene world)
|
||||
{
|
||||
Mario.instance = this;
|
||||
this.world = world;
|
||||
keys = Scene.keys;
|
||||
x = 32;
|
||||
y = 0;
|
||||
|
||||
facing = 1;
|
||||
|
||||
//TODO: REMOVE THESE TEST VARIABLES
|
||||
// Mario.large = true;
|
||||
// Mario.fire = true;
|
||||
|
||||
setLarge(Mario.large, Mario.fire);
|
||||
}
|
||||
|
||||
private boolean lastLarge;
|
||||
private boolean lastFire;
|
||||
private boolean newLarge;
|
||||
private boolean newFire;
|
||||
|
||||
private void blink(boolean on)
|
||||
{
|
||||
Mario.large = on?newLarge:lastLarge;
|
||||
Mario.fire = on?newFire:lastFire;
|
||||
|
||||
if (large)
|
||||
{
|
||||
sheet = Art.mario;
|
||||
if (fire)
|
||||
sheet = Art.fireMario;
|
||||
|
||||
xPicO = 16;
|
||||
yPicO = 31;
|
||||
wPic = hPic = 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
sheet = Art.smallMario;
|
||||
|
||||
xPicO = 8;
|
||||
yPicO = 15;
|
||||
wPic = hPic = 16;
|
||||
}
|
||||
|
||||
calcPic();
|
||||
}
|
||||
|
||||
void setLarge(boolean large, boolean fire)
|
||||
{
|
||||
if (fire) large = true;
|
||||
if (!large) fire = false;
|
||||
|
||||
lastLarge = Mario.large;
|
||||
lastFire = Mario.fire;
|
||||
|
||||
Mario.large = large;
|
||||
Mario.fire = fire;
|
||||
|
||||
newLarge = Mario.large;
|
||||
newFire = Mario.fire;
|
||||
|
||||
blink(true);
|
||||
}
|
||||
|
||||
public void move()
|
||||
{
|
||||
if(deathTime == 0 && winTime == 0){
|
||||
if (keys[KEY_DOWN] && large && ducking)
|
||||
{
|
||||
if(world.recorder != null && world.recorder.recording)
|
||||
world.recorder.startDuckRecord();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(world.recorder != null && world.recorder.recording && !ducking)
|
||||
world.recorder.endDuckRecord();
|
||||
}
|
||||
}
|
||||
|
||||
if(deathTime == 0 && winTime == 0){
|
||||
if(keys[KEY_SPEED]){
|
||||
if(world.recorder!= null && world.recorder.recording){
|
||||
world.recorder.startRunningRecord();
|
||||
}
|
||||
|
||||
running = true;
|
||||
}
|
||||
else{
|
||||
if(world.recorder!= null && world.recorder.recording){
|
||||
world.recorder.endRunningRecord();
|
||||
}
|
||||
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (winTime > 0)
|
||||
{
|
||||
|
||||
winTime++;
|
||||
|
||||
xa = 0;
|
||||
ya = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (deathTime > 0)
|
||||
{
|
||||
deathTime++;
|
||||
if (deathTime < 11)
|
||||
{
|
||||
xa = 0;
|
||||
ya = 0;
|
||||
}
|
||||
else if (deathTime == 11)
|
||||
{
|
||||
ya = -15;
|
||||
}
|
||||
else
|
||||
{
|
||||
ya += 2;
|
||||
}
|
||||
x += xa;
|
||||
y += ya;
|
||||
return;
|
||||
}
|
||||
|
||||
if (powerUpTime != 0)
|
||||
{
|
||||
if (powerUpTime > 0)
|
||||
{
|
||||
powerUpTime--;
|
||||
blink(((powerUpTime / 3) & 1) == 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
powerUpTime++;
|
||||
blink(((-powerUpTime / 3) & 1) == 0);
|
||||
}
|
||||
|
||||
if (powerUpTime == 0) world.paused = false;
|
||||
|
||||
calcPic();
|
||||
return;
|
||||
}
|
||||
|
||||
if (invulnerableTime > 0) invulnerableTime--;
|
||||
visible = ((invulnerableTime / 2) & 1) == 0;
|
||||
|
||||
wasOnGround = onGround;
|
||||
float sideWaysSpeed = keys[KEY_SPEED] ? 1.2f : 0.6f;
|
||||
// float sideWaysSpeed = onGround ? 2.5f : 1.2f;
|
||||
|
||||
if (onGround)
|
||||
{
|
||||
if (keys[KEY_DOWN] && large)
|
||||
{
|
||||
if(world.recorder != null)
|
||||
world.recorder.startDuckRecord();
|
||||
|
||||
ducking = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(world.recorder != null)
|
||||
world.recorder.endDuckRecord();
|
||||
|
||||
ducking = false;
|
||||
}
|
||||
|
||||
if(world.recorder != null)
|
||||
world.recorder.recordJumpLand();
|
||||
}
|
||||
|
||||
if (xa > 2)
|
||||
{
|
||||
facing = 1;
|
||||
}
|
||||
if (xa < -2)
|
||||
{
|
||||
facing = -1;
|
||||
}
|
||||
|
||||
if (keys[KEY_JUMP] || (jumpTime < 0 && !onGround && !sliding))
|
||||
{
|
||||
if (jumpTime < 0)
|
||||
{
|
||||
xa = xJumpSpeed;
|
||||
ya = -jumpTime * yJumpSpeed;
|
||||
jumpTime++;
|
||||
}
|
||||
else if (onGround && mayJump)
|
||||
{
|
||||
world.sound.play(Art.samples[Art.SAMPLE_MARIO_JUMP], this, 1, 1, 1);
|
||||
xJumpSpeed = 0;
|
||||
yJumpSpeed = -1.9f;
|
||||
jumpTime = 7;
|
||||
ya = jumpTime * yJumpSpeed;
|
||||
onGround = false;
|
||||
sliding = false;
|
||||
|
||||
if(world.recorder != null){
|
||||
world.recorder.isInAir = true;
|
||||
world.recorder.recordJump();
|
||||
}
|
||||
}
|
||||
else if (sliding && mayJump)
|
||||
{
|
||||
world.sound.play(Art.samples[Art.SAMPLE_MARIO_JUMP], this, 1, 1, 1);
|
||||
xJumpSpeed = -facing * 6.0f;
|
||||
yJumpSpeed = -2.0f;
|
||||
jumpTime = -6;
|
||||
xa = xJumpSpeed;
|
||||
ya = -jumpTime * yJumpSpeed;
|
||||
onGround = false;
|
||||
sliding = false;
|
||||
facing = -facing;
|
||||
}
|
||||
else if (jumpTime > 0)
|
||||
{
|
||||
xa += xJumpSpeed;
|
||||
ya = jumpTime * yJumpSpeed;
|
||||
jumpTime--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
jumpTime = 0;
|
||||
}
|
||||
|
||||
if(world.mario.xa > 0){
|
||||
|
||||
if(direction != 1){
|
||||
direction = 1;
|
||||
if(world.recorder != null){
|
||||
// world.recorder.switchRecord();
|
||||
world.recorder.startRightMoveRecord();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if(world.mario.xa < 0){
|
||||
if(direction != -1){
|
||||
direction = -1;
|
||||
if(world.recorder != null){
|
||||
// world.recorder.switchRecord();
|
||||
world.recorder.startLeftMoveRecord();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else{
|
||||
//was moving right
|
||||
if(direction == 1 && world.recorder!= null){
|
||||
world.recorder.endRightMoveRecord();
|
||||
}
|
||||
//was moving left
|
||||
else if(direction == -1 && world.recorder!= null){
|
||||
world.recorder.endLeftMoveRecord();
|
||||
}
|
||||
|
||||
direction = 0;
|
||||
}
|
||||
|
||||
if (keys[KEY_LEFT] && !ducking)
|
||||
{
|
||||
if (facing == 1) sliding = false;
|
||||
xa -= sideWaysSpeed;
|
||||
if (jumpTime >= 0) facing = -1;
|
||||
}
|
||||
|
||||
if (keys[KEY_RIGHT] && !ducking)
|
||||
{
|
||||
if (facing == -1) sliding = false;
|
||||
xa += sideWaysSpeed;
|
||||
if (jumpTime >= 0) facing = 1;
|
||||
}
|
||||
|
||||
if ((!keys[KEY_LEFT] && !keys[KEY_RIGHT]) || ducking || ya < 0 || onGround)
|
||||
{
|
||||
sliding = false;
|
||||
}
|
||||
|
||||
if (keys[KEY_SPEED] && canShoot && Mario.fire && world.fireballsOnScreen<2)
|
||||
{
|
||||
world.sound.play(Art.samples[Art.SAMPLE_MARIO_FIREBALL], this, 1, 1, 1);
|
||||
world.addSprite(new Fireball(world, x+facing*6, y-20, facing));
|
||||
}
|
||||
|
||||
canShoot = !keys[KEY_SPEED];
|
||||
|
||||
mayJump = (onGround || sliding) && !keys[KEY_JUMP];
|
||||
|
||||
xFlipPic = facing == -1;
|
||||
|
||||
runTime += (Math.abs(xa)) + 5;
|
||||
if (Math.abs(xa) < 0.5f)
|
||||
{
|
||||
runTime = 0;
|
||||
xa = 0;
|
||||
}
|
||||
|
||||
calcPic();
|
||||
|
||||
if (sliding)
|
||||
{
|
||||
for (int i = 0; i < 1; i++)
|
||||
{
|
||||
world.addSprite(new Sparkle((int) (x + Math.random() * 4 - 2) + facing * 8, (int) (y + Math.random() * 4) - 24, (float) (Math.random() * 2 - 1), (float) Math.random() * 1, 0, 1, 5));
|
||||
}
|
||||
ya *= 0.5f;
|
||||
}
|
||||
|
||||
onGround = false;
|
||||
move(xa, 0);
|
||||
move(0, ya);
|
||||
|
||||
if (y > world.level.getHeight() * 16 + 16)
|
||||
{
|
||||
dieJump();
|
||||
}
|
||||
|
||||
if (x < 0)
|
||||
{
|
||||
x = 0;
|
||||
xa = 0;
|
||||
}
|
||||
|
||||
// if(x > world.level.xExit * 16 && ! world.level.flipped || x < world.level.xExit * 16 && world.level.flipped )
|
||||
if(x > world.level.getxExit() * 16 )
|
||||
|
||||
{
|
||||
win();
|
||||
}
|
||||
|
||||
if (x > world.level.getWidth() * 16)
|
||||
{
|
||||
x = world.level.getWidth() * 16;
|
||||
xa = 0;
|
||||
}
|
||||
|
||||
ya *= 0.85f;
|
||||
if (onGround)
|
||||
{
|
||||
xa *= GROUND_INERTIA;
|
||||
}
|
||||
else
|
||||
{
|
||||
xa *= AIR_INERTIA;
|
||||
}
|
||||
|
||||
if (!onGround)
|
||||
{
|
||||
ya += 3;
|
||||
}
|
||||
|
||||
if (carried != null)
|
||||
{
|
||||
carried.x = x + facing * 8;
|
||||
carried.y = y - 2;
|
||||
if (!keys[KEY_SPEED])
|
||||
{
|
||||
carried.release(this);
|
||||
carried = null;
|
||||
|
||||
if(world.recorder != null){
|
||||
world.recorder.shellUnleashedRecord();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void calcPic()
|
||||
{
|
||||
int runFrame = 0;
|
||||
|
||||
if (large)
|
||||
{
|
||||
runFrame = ((int) (runTime / 20)) % 4;
|
||||
if (runFrame == 3) runFrame = 1;
|
||||
if (carried == null && Math.abs(xa) > 10) runFrame += 3;
|
||||
if (carried != null) runFrame += 10;
|
||||
if (!onGround)
|
||||
{
|
||||
if (carried != null) runFrame = 12;
|
||||
else if (Math.abs(xa) > 10) runFrame = 7;
|
||||
else runFrame = 6;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
runFrame = ((int) (runTime / 20)) % 2;
|
||||
if (carried == null && Math.abs(xa) > 10) runFrame += 2;
|
||||
if (carried != null) runFrame += 8;
|
||||
if (!onGround)
|
||||
{
|
||||
if (carried != null) runFrame = 9;
|
||||
else if (Math.abs(xa) > 10) runFrame = 5;
|
||||
else runFrame = 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (onGround && ((facing == -1 && xa > 0) || (facing == 1 && xa < 0)))
|
||||
{
|
||||
if (xa > 1 || xa < -1) runFrame = large ? 9 : 7;
|
||||
|
||||
if (xa > 3 || xa < -3)
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
world.addSprite(new Sparkle((int) (x + Math.random() * 8 - 4), (int) (y + Math.random() * 4), (float) (Math.random() * 2 - 1), (float) Math.random() * -1, 0, 1, 5));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (large)
|
||||
{
|
||||
if (ducking) runFrame = 14;
|
||||
height = ducking ? 12 : 24;
|
||||
}
|
||||
else
|
||||
{
|
||||
height = 12;
|
||||
}
|
||||
|
||||
xPic = runFrame;
|
||||
}
|
||||
|
||||
private boolean move(float xa, float ya)
|
||||
{
|
||||
|
||||
while (xa > 8)
|
||||
{
|
||||
if (!move(8, 0)) return false;
|
||||
xa -= 8;
|
||||
}
|
||||
while (xa < -8)
|
||||
{
|
||||
if (!move(-8, 0)) return false;
|
||||
xa += 8;
|
||||
}
|
||||
while (ya > 8)
|
||||
{
|
||||
if (!move(0, 8)) return false;
|
||||
ya -= 8;
|
||||
}
|
||||
while (ya < -8)
|
||||
{
|
||||
if (!move(0, -8)) return false;
|
||||
ya += 8;
|
||||
}
|
||||
|
||||
boolean collide = false;
|
||||
if (ya > 0)
|
||||
{
|
||||
if (isBlocking(x + xa - width, y + ya, xa, 0)) collide = true;
|
||||
else if (isBlocking(x + xa + width, y + ya, xa, 0)) collide = true;
|
||||
else if (isBlocking(x + xa - width, y + ya + 1, xa, ya)) collide = true;
|
||||
else if (isBlocking(x + xa + width, y + ya + 1, xa, ya)) collide = true;
|
||||
}
|
||||
if (ya < 0)
|
||||
{
|
||||
if (isBlocking(x + xa, y + ya - height, xa, ya)) collide = true;
|
||||
else if (collide || isBlocking(x + xa - width, y + ya - height, xa, ya)) collide = true;
|
||||
else if (collide || isBlocking(x + xa + width, y + ya - height, xa, ya)) collide = true;
|
||||
}
|
||||
if (xa > 0)
|
||||
{
|
||||
sliding = true;
|
||||
if (isBlocking(x + xa + width, y + ya - height, xa, ya)) collide = true;
|
||||
else sliding = false;
|
||||
if (isBlocking(x + xa + width, y + ya - height / 2, xa, ya)) collide = true;
|
||||
else sliding = false;
|
||||
if (isBlocking(x + xa + width, y + ya, xa, ya)) collide = true;
|
||||
else sliding = false;
|
||||
}
|
||||
if (xa < 0)
|
||||
{
|
||||
sliding = true;
|
||||
if (isBlocking(x + xa - width, y + ya - height, xa, ya)) collide = true;
|
||||
else sliding = false;
|
||||
if (isBlocking(x + xa - width, y + ya - height / 2, xa, ya)) collide = true;
|
||||
else sliding = false;
|
||||
if (isBlocking(x + xa - width, y + ya, xa, ya)) collide = true;
|
||||
else sliding = false;
|
||||
}
|
||||
|
||||
if (collide)
|
||||
{
|
||||
if (xa < 0)
|
||||
{
|
||||
x = (int) ((x - width) / 16) * 16 + width;
|
||||
this.xa = 0;
|
||||
}
|
||||
if (xa > 0)
|
||||
{
|
||||
x = (int) ((x + width) / 16 + 1) * 16 - width - 1;
|
||||
this.xa = 0;
|
||||
}
|
||||
if (ya < 0)
|
||||
{
|
||||
y = (int) ((y - height) / 16) * 16 + height;
|
||||
jumpTime = 0;
|
||||
this.ya = 0;
|
||||
}
|
||||
if (ya > 0)
|
||||
{
|
||||
y = (int) ((y - 1) / 16 + 1) * 16 - 1;
|
||||
onGround = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
x += xa;
|
||||
y += ya;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBlocking(float _x, float _y, float xa, float ya)
|
||||
{
|
||||
//translate into block mode (since blocks are 16x16)
|
||||
int x = (int) (_x / 16);
|
||||
int y = (int) (_y / 16);
|
||||
|
||||
if (x==(int)(this.x/16) && y==(int)(this.y/16))
|
||||
return false;
|
||||
|
||||
boolean blocking = world.level.isBlocking(x, y, xa, ya);
|
||||
|
||||
byte block = world.level.getBlock(x, y);
|
||||
|
||||
if (((Level.TILE_BEHAVIORS[block & 0xff]) & Level.BIT_PICKUPABLE) > 0)
|
||||
{
|
||||
if(world.recorder != null)
|
||||
world.recorder.recordCoin();
|
||||
|
||||
Mario.getCoin();
|
||||
world.sound.play(Art.samples[Art.SAMPLE_GET_COIN], new FixedSoundSource(x * 16 + 8, y * 16 + 8), 1, 1, 1);
|
||||
world.level.setBlock(x, y, (byte) 0);
|
||||
for (int xx = 0; xx < 2; xx++)
|
||||
for (int yy = 0; yy < 2; yy++)
|
||||
world.addSprite(new Sparkle(x * 16 + xx * 8 + (int) (Math.random() * 8), y * 16 + yy * 8 + (int) (Math.random() * 8), 0, 0, 0, 2, 5));
|
||||
}
|
||||
|
||||
if (blocking && ya < 0)
|
||||
{
|
||||
world.bump(x, y, large);
|
||||
}
|
||||
|
||||
return blocking;
|
||||
}
|
||||
|
||||
public void stomp(Enemy enemy)
|
||||
{
|
||||
if (deathTime > 0 || world.paused) return;
|
||||
|
||||
float targetY = enemy.y - enemy.height / 2;
|
||||
move(0, targetY - y);
|
||||
|
||||
world.sound.play(Art.samples[Art.SAMPLE_MARIO_KICK], this, 1, 1, 1);
|
||||
xJumpSpeed = 0;
|
||||
yJumpSpeed = -1.9f;
|
||||
jumpTime = 8;
|
||||
ya = jumpTime * yJumpSpeed;
|
||||
onGround = false;
|
||||
sliding = false;
|
||||
invulnerableTime = 1;
|
||||
|
||||
if(world.recorder!=null)
|
||||
world.recorder.killStompRecord(enemy);
|
||||
}
|
||||
|
||||
public void stomp(Shell shell)
|
||||
{
|
||||
if (deathTime > 0 || world.paused) return;
|
||||
|
||||
if (keys[KEY_SPEED] && shell.facing == 0)
|
||||
{
|
||||
carried = shell;
|
||||
shell.carried = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
float targetY = shell.y - shell.height / 2;
|
||||
move(0, targetY - y);
|
||||
|
||||
world.sound.play(Art.samples[Art.SAMPLE_MARIO_KICK], this, 1, 1, 1);
|
||||
xJumpSpeed = 0;
|
||||
yJumpSpeed = -1.9f;
|
||||
jumpTime = 8;
|
||||
ya = jumpTime * yJumpSpeed;
|
||||
onGround = false;
|
||||
sliding = false;
|
||||
invulnerableTime = 1;
|
||||
|
||||
if(shell.xa == 0 && world.recorder!= null){
|
||||
world.recorder.shellUnleashedRecord();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void getHurt(Sprite sprite)
|
||||
{
|
||||
if (deathTime > 0 || world.paused) return;
|
||||
if (invulnerableTime > 0) return;
|
||||
|
||||
if (large)
|
||||
{
|
||||
world.paused = true;
|
||||
powerUpTime = -3 * 6;
|
||||
world.sound.play(Art.samples[Art.SAMPLE_MARIO_POWER_DOWN], this, 1, 1, 1);
|
||||
if (fire)
|
||||
{
|
||||
world.mario.setLarge(true, false);
|
||||
|
||||
if(world.recorder != null){
|
||||
world.recorder.endFireRecord();
|
||||
world.recorder.startLargeRecord();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
world.mario.setLarge(false, false);
|
||||
|
||||
if(world.recorder != null){
|
||||
world.recorder.endLargeRecord();
|
||||
world.recorder.startLittleRecord();
|
||||
}
|
||||
}
|
||||
invulnerableTime = 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
dieSprite(sprite);
|
||||
}
|
||||
}
|
||||
|
||||
private void win()
|
||||
{
|
||||
xDeathPos = (int) x;
|
||||
yDeathPos = (int) y;
|
||||
world.paused = true;
|
||||
winTime = 1;
|
||||
Art.stopMusic();
|
||||
world.sound.play(Art.samples[Art.SAMPLE_LEVEL_EXIT], this, 1, 1, 1);
|
||||
}
|
||||
|
||||
public void dieSprite(Sprite sprite){
|
||||
die();
|
||||
|
||||
if(world.recorder != null){
|
||||
world.recorder.dieRecord(sprite);
|
||||
}
|
||||
}
|
||||
|
||||
public void dieTime(){
|
||||
die();
|
||||
|
||||
if(world.recorder!=null){
|
||||
world.recorder.dieTimeRecord();
|
||||
}
|
||||
}
|
||||
|
||||
public void dieJump(){
|
||||
die();
|
||||
|
||||
if(world.recorder!=null){
|
||||
world.recorder.dieJumpRecord();
|
||||
}
|
||||
}
|
||||
|
||||
public void die()
|
||||
{
|
||||
xDeathPos = (int) x;
|
||||
yDeathPos = (int) y;
|
||||
world.paused = true;
|
||||
deathTime = 1;
|
||||
Art.stopMusic();
|
||||
world.sound.play(Art.samples[Art.SAMPLE_MARIO_DEATH], this, 1, 1, 1);
|
||||
|
||||
if(world.recorder != null){
|
||||
|
||||
|
||||
if(running)
|
||||
world.recorder.endRunningRecord();
|
||||
|
||||
if(large && !fire){
|
||||
world.recorder.endLargeRecord();
|
||||
}
|
||||
|
||||
if(fire){
|
||||
world.recorder.endFireRecord();
|
||||
}
|
||||
|
||||
if(!large && !fire)
|
||||
world.recorder.endLittleRecord();
|
||||
|
||||
if(ducking)
|
||||
world.recorder.endDuckRecord();
|
||||
|
||||
world.recorder.endTime();
|
||||
world.recorder.recordJumpLand();
|
||||
}
|
||||
|
||||
large = false;
|
||||
fire = false;
|
||||
}
|
||||
|
||||
|
||||
public void getFlower()
|
||||
{
|
||||
if (deathTime > 0 || world.paused) return;
|
||||
|
||||
if (!fire)
|
||||
{
|
||||
world.paused = true;
|
||||
powerUpTime = 3 * 6;
|
||||
world.sound.play(Art.samples[Art.SAMPLE_MARIO_POWER_UP], this, 1, 1, 1);
|
||||
world.mario.setLarge(true, true);
|
||||
|
||||
if(world.recorder != null){
|
||||
if(large){
|
||||
world.recorder.endLargeRecord();
|
||||
|
||||
}
|
||||
else{
|
||||
world.recorder.endLittleRecord();
|
||||
}
|
||||
|
||||
world.recorder.startFireRecord();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Mario.getCoin();
|
||||
world.sound.play(Art.samples[Art.SAMPLE_GET_COIN], this, 1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void getMushroom()
|
||||
{
|
||||
if (deathTime > 0 || world.paused) return;
|
||||
|
||||
if (!large)
|
||||
{
|
||||
world.paused = true;
|
||||
powerUpTime = 3 * 6;
|
||||
world.sound.play(Art.samples[Art.SAMPLE_MARIO_POWER_UP], this, 1, 1, 1);
|
||||
world.mario.setLarge(true, false);
|
||||
|
||||
if(world.recorder != null){
|
||||
world.recorder.endLittleRecord();
|
||||
world.recorder.startLargeRecord();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Mario.getCoin();
|
||||
world.sound.play(Art.samples[Art.SAMPLE_GET_COIN], this, 1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void kick(Shell shell)
|
||||
{
|
||||
if (deathTime > 0 || world.paused) return;
|
||||
|
||||
if (keys[KEY_SPEED])
|
||||
{
|
||||
carried = shell;
|
||||
shell.carried = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
world.sound.play(Art.samples[Art.SAMPLE_MARIO_KICK], this, 1, 1, 1);
|
||||
invulnerableTime = 1;
|
||||
|
||||
if(world.recorder!=null)
|
||||
world.recorder.shellUnleashedRecord();
|
||||
}
|
||||
}
|
||||
|
||||
public void stomp(BulletBill bill)
|
||||
{
|
||||
if (deathTime > 0 || world.paused) return;
|
||||
|
||||
float targetY = bill.y - bill.height / 2;
|
||||
move(0, targetY - y);
|
||||
|
||||
world.sound.play(Art.samples[Art.SAMPLE_MARIO_KICK], this, 1, 1, 1);
|
||||
xJumpSpeed = 0;
|
||||
yJumpSpeed = -1.9f;
|
||||
jumpTime = 8;
|
||||
ya = jumpTime * yJumpSpeed;
|
||||
onGround = false;
|
||||
sliding = false;
|
||||
invulnerableTime = 1;
|
||||
|
||||
if(world.recorder!=null)
|
||||
world.recorder.killStompRecord(bill);
|
||||
}
|
||||
|
||||
public byte getKeyMask()
|
||||
{
|
||||
int mask = 0;
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
if (keys[i]) mask |= (1 << i);
|
||||
}
|
||||
return (byte) mask;
|
||||
}
|
||||
|
||||
public void setKeys(byte mask)
|
||||
{
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
keys[i] = (mask & (1 << i)) > 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static void get1Up()
|
||||
{
|
||||
instance.world.sound.play(Art.samples[Art.SAMPLE_MARIO_1UP], instance, 1, 1, 1);
|
||||
lives++;
|
||||
if (lives==99)
|
||||
{
|
||||
lives = 99;
|
||||
}
|
||||
}
|
||||
|
||||
public static void getCoin()
|
||||
{
|
||||
coins++;
|
||||
if (coins==100)
|
||||
{
|
||||
coins = 0;
|
||||
get1Up();
|
||||
}
|
||||
}
|
||||
}
|
||||
223
src/dk/itu/mario/engine/sprites/Mushroom.java
Normal file
223
src/dk/itu/mario/engine/sprites/Mushroom.java
Normal file
@@ -0,0 +1,223 @@
|
||||
package dk.itu.mario.engine.sprites;
|
||||
|
||||
|
||||
import dk.itu.mario.engine.Art;
|
||||
import dk.itu.mario.scene.LevelScene;
|
||||
|
||||
|
||||
|
||||
public class Mushroom extends Sprite
|
||||
{
|
||||
private static float GROUND_INERTIA = 0.89f;
|
||||
private static float AIR_INERTIA = 0.89f;
|
||||
|
||||
private float runTime;
|
||||
private boolean onGround = false;
|
||||
private boolean mayJump = false;
|
||||
private int jumpTime = 0;
|
||||
private float xJumpSpeed;
|
||||
private float yJumpSpeed;
|
||||
|
||||
private int width = 4;
|
||||
int height = 24;
|
||||
|
||||
private LevelScene world;
|
||||
public int facing;
|
||||
|
||||
public boolean avoidCliffs = false;
|
||||
private int life;
|
||||
|
||||
public Mushroom(LevelScene world, int x, int y)
|
||||
{
|
||||
sheet = Art.items;
|
||||
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.world = world;
|
||||
xPicO = 8;
|
||||
yPicO = 15;
|
||||
|
||||
yPic = 0;
|
||||
height = 12;
|
||||
facing = 1;
|
||||
wPic = hPic = 16;
|
||||
life = 0;
|
||||
}
|
||||
|
||||
public void collideCheck()
|
||||
{
|
||||
float xMarioD = world.mario.x - x;
|
||||
float yMarioD = world.mario.y - y;
|
||||
float w = 16;
|
||||
if (xMarioD > -16 && xMarioD < 16)
|
||||
{
|
||||
if (yMarioD > -height && yMarioD < world.mario.height)
|
||||
{
|
||||
world.mario.getMushroom();
|
||||
spriteContext.removeSprite(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void move()
|
||||
{
|
||||
if (life<9)
|
||||
{
|
||||
layer = 0;
|
||||
y--;
|
||||
life++;
|
||||
return;
|
||||
}
|
||||
float sideWaysSpeed = 1.75f;
|
||||
layer = 1;
|
||||
// float sideWaysSpeed = onGround ? 2.5f : 1.2f;
|
||||
|
||||
if (xa > 2)
|
||||
{
|
||||
facing = 1;
|
||||
}
|
||||
if (xa < -2)
|
||||
{
|
||||
facing = -1;
|
||||
}
|
||||
|
||||
xa = facing * sideWaysSpeed;
|
||||
|
||||
mayJump = (onGround);
|
||||
|
||||
xFlipPic = facing == -1;
|
||||
|
||||
runTime += (Math.abs(xa)) + 5;
|
||||
|
||||
|
||||
|
||||
if (!move(xa, 0)) facing = -facing;
|
||||
onGround = false;
|
||||
move(0, ya);
|
||||
|
||||
ya *= 0.85f;
|
||||
if (onGround)
|
||||
{
|
||||
xa *= GROUND_INERTIA;
|
||||
}
|
||||
else
|
||||
{
|
||||
xa *= AIR_INERTIA;
|
||||
}
|
||||
|
||||
if (!onGround)
|
||||
{
|
||||
ya += 2;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean move(float xa, float ya)
|
||||
{
|
||||
while (xa > 8)
|
||||
{
|
||||
if (!move(8, 0)) return false;
|
||||
xa -= 8;
|
||||
}
|
||||
while (xa < -8)
|
||||
{
|
||||
if (!move(-8, 0)) return false;
|
||||
xa += 8;
|
||||
}
|
||||
while (ya > 8)
|
||||
{
|
||||
if (!move(0, 8)) return false;
|
||||
ya -= 8;
|
||||
}
|
||||
while (ya < -8)
|
||||
{
|
||||
if (!move(0, -8)) return false;
|
||||
ya += 8;
|
||||
}
|
||||
|
||||
boolean collide = false;
|
||||
if (ya > 0)
|
||||
{
|
||||
if (isBlocking(x + xa - width, y + ya, xa, 0)) collide = true;
|
||||
else if (isBlocking(x + xa + width, y + ya, xa, 0)) collide = true;
|
||||
else if (isBlocking(x + xa - width, y + ya + 1, xa, ya)) collide = true;
|
||||
else if (isBlocking(x + xa + width, y + ya + 1, xa, ya)) collide = true;
|
||||
}
|
||||
if (ya < 0)
|
||||
{
|
||||
if (isBlocking(x + xa, y + ya - height, xa, ya)) collide = true;
|
||||
else if (collide || isBlocking(x + xa - width, y + ya - height, xa, ya)) collide = true;
|
||||
else if (collide || isBlocking(x + xa + width, y + ya - height, xa, ya)) collide = true;
|
||||
}
|
||||
if (xa > 0)
|
||||
{
|
||||
if (isBlocking(x + xa + width, y + ya - height, xa, ya)) collide = true;
|
||||
if (isBlocking(x + xa + width, y + ya - height / 2, xa, ya)) collide = true;
|
||||
if (isBlocking(x + xa + width, y + ya, xa, ya)) collide = true;
|
||||
|
||||
if (avoidCliffs && onGround && !world.level.isBlocking((int) ((x + xa + width) / 16), (int) ((y) / 16 + 1), xa, 1)) collide = true;
|
||||
}
|
||||
if (xa < 0)
|
||||
{
|
||||
if (isBlocking(x + xa - width, y + ya - height, xa, ya)) collide = true;
|
||||
if (isBlocking(x + xa - width, y + ya - height / 2, xa, ya)) collide = true;
|
||||
if (isBlocking(x + xa - width, y + ya, xa, ya)) collide = true;
|
||||
|
||||
if (avoidCliffs && onGround && !world.level.isBlocking((int) ((x + xa - width) / 16), (int) ((y) / 16 + 1), xa, 1)) collide = true;
|
||||
}
|
||||
|
||||
if (collide)
|
||||
{
|
||||
if (xa < 0)
|
||||
{
|
||||
x = (int) ((x - width) / 16) * 16 + width;
|
||||
this.xa = 0;
|
||||
}
|
||||
if (xa > 0)
|
||||
{
|
||||
x = (int) ((x + width) / 16 + 1) * 16 - width - 1;
|
||||
this.xa = 0;
|
||||
}
|
||||
if (ya < 0)
|
||||
{
|
||||
y = (int) ((y - height) / 16) * 16 + height;
|
||||
jumpTime = 0;
|
||||
this.ya = 0;
|
||||
}
|
||||
if (ya > 0)
|
||||
{
|
||||
y = (int) (y / 16 + 1) * 16 - 1;
|
||||
onGround = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
x += xa;
|
||||
y += ya;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBlocking(float _x, float _y, float xa, float ya)
|
||||
{
|
||||
int x = (int) (_x / 16);
|
||||
int y = (int) (_y / 16);
|
||||
if (x == (int) (this.x / 16) && y == (int) (this.y / 16)) return false;
|
||||
|
||||
boolean blocking = world.level.isBlocking(x, y, xa, ya);
|
||||
|
||||
byte block = world.level.getBlock(x, y);
|
||||
|
||||
return blocking;
|
||||
}
|
||||
|
||||
public void bumpCheck(int xTile, int yTile)
|
||||
{
|
||||
if (x + width > xTile * 16 && x - width < xTile * 16 + 16 && yTile==(int)((y-1)/16))
|
||||
{
|
||||
facing = -world.mario.facing;
|
||||
ya = -10;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
40
src/dk/itu/mario/engine/sprites/Particle.java
Normal file
40
src/dk/itu/mario/engine/sprites/Particle.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package dk.itu.mario.engine.sprites;
|
||||
|
||||
import dk.itu.mario.engine.Art;
|
||||
|
||||
|
||||
public class Particle extends Sprite
|
||||
{
|
||||
public int life;
|
||||
|
||||
public Particle(int x, int y, float xa, float ya)
|
||||
{
|
||||
this(x, y, xa, ya, (int)(Math.random()*2), 0);
|
||||
}
|
||||
|
||||
public Particle(int x, int y, float xa, float ya, int xPic, int yPic)
|
||||
{
|
||||
sheet = Art.particles;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.xa = xa;
|
||||
this.ya = ya;
|
||||
this.xPic = xPic;
|
||||
this.yPic = yPic;
|
||||
this.xPicO = 4;
|
||||
this.yPicO = 4;
|
||||
|
||||
wPic = 8;
|
||||
hPic = 8;
|
||||
life = 10;
|
||||
}
|
||||
|
||||
public void move()
|
||||
{
|
||||
if (life--<0) Sprite.spriteContext.removeSprite(this);
|
||||
x+=xa;
|
||||
y+=ya;
|
||||
ya*=0.95f;
|
||||
ya+=3;
|
||||
}
|
||||
}
|
||||
370
src/dk/itu/mario/engine/sprites/Shell.java
Normal file
370
src/dk/itu/mario/engine/sprites/Shell.java
Normal file
@@ -0,0 +1,370 @@
|
||||
package dk.itu.mario.engine.sprites;
|
||||
|
||||
|
||||
import dk.itu.mario.engine.Art;
|
||||
import dk.itu.mario.scene.LevelScene;
|
||||
|
||||
|
||||
|
||||
|
||||
public class Shell extends Sprite
|
||||
{
|
||||
private static float GROUND_INERTIA = 0.89f;
|
||||
private static float AIR_INERTIA = 0.89f;
|
||||
|
||||
private float runTime;
|
||||
private boolean onGround = false;
|
||||
|
||||
private int width = 4;
|
||||
int height = 24;
|
||||
|
||||
private LevelScene world;
|
||||
public int facing;
|
||||
|
||||
public boolean avoidCliffs = false;
|
||||
public int anim;
|
||||
|
||||
public boolean dead = false;
|
||||
private int deadTime = 0;
|
||||
public boolean carried;
|
||||
|
||||
|
||||
public Shell(LevelScene world, float x, float y, int type)
|
||||
{
|
||||
sheet = Art.enemies;
|
||||
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.world = world;
|
||||
xPicO = 8;
|
||||
yPicO = 31;
|
||||
|
||||
yPic = type;
|
||||
height = 12;
|
||||
facing = 0;
|
||||
wPic = 16;
|
||||
|
||||
xPic = 4;
|
||||
ya = -5;
|
||||
}
|
||||
|
||||
public boolean fireballCollideCheck(Fireball fireball)
|
||||
{
|
||||
if (deadTime != 0) return false;
|
||||
|
||||
float xD = fireball.x - x;
|
||||
float yD = fireball.y - y;
|
||||
|
||||
if (xD > -16 && xD < 16)
|
||||
{
|
||||
if (yD > -height && yD < fireball.height)
|
||||
{
|
||||
if (facing!=0) return true;
|
||||
|
||||
world.sound.play(Art.samples[Art.SAMPLE_MARIO_KICK], this, 1, 1, 1);
|
||||
|
||||
xa = fireball.facing * 2;
|
||||
ya = -5;
|
||||
if (spriteTemplate != null) spriteTemplate.isDead = true;
|
||||
deadTime = 100;
|
||||
hPic = -hPic;
|
||||
yPicO = -yPicO + 16;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void collideCheck()
|
||||
{
|
||||
if (carried || dead || deadTime>0) return;
|
||||
|
||||
float xMarioD = world.mario.x - x;
|
||||
float yMarioD = world.mario.y - y;
|
||||
float w = 16;
|
||||
if (xMarioD > -16 && xMarioD < 16)
|
||||
{
|
||||
if (yMarioD > -height && yMarioD < world.mario.height)
|
||||
{
|
||||
if (world.mario.ya > 0 && yMarioD <= 0 && (!world.mario.onGround || !world.mario.wasOnGround))
|
||||
{
|
||||
world.mario.stomp(this);
|
||||
if (facing != 0)
|
||||
{
|
||||
xa = 0;
|
||||
facing = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
facing = world.mario.facing;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (facing != 0)
|
||||
{
|
||||
world.mario.getHurt(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
world.mario.kick(this);
|
||||
facing = world.mario.facing;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void move()
|
||||
{
|
||||
if (y > world.level.getHeight() * 16 + 16 && deadTime == 0)
|
||||
{
|
||||
die();
|
||||
spriteContext.removeSprite(this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (carried)
|
||||
{
|
||||
world.checkShellCollide(this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (deadTime > 0)
|
||||
{
|
||||
deadTime--;
|
||||
|
||||
if (deadTime == 0)
|
||||
{
|
||||
deadTime = 1;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
world.addSprite(new Sparkle((int) (x + Math.random() * 16 - 8) + 4, (int) (y - Math.random() * 8) + 4, (float) (Math.random() * 2 - 1), (float) Math.random() * -1, 0, 1, 5));
|
||||
}
|
||||
spriteContext.removeSprite(this);
|
||||
}
|
||||
|
||||
x += xa;
|
||||
y += ya;
|
||||
ya *= 0.95;
|
||||
ya += 1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (facing != 0) anim++;
|
||||
|
||||
float sideWaysSpeed = 11f;
|
||||
// float sideWaysSpeed = onGround ? 2.5f : 1.2f;
|
||||
|
||||
if (xa > 2)
|
||||
{
|
||||
facing = 1;
|
||||
}
|
||||
if (xa < -2)
|
||||
{
|
||||
facing = -1;
|
||||
}
|
||||
|
||||
xa = facing * sideWaysSpeed;
|
||||
|
||||
if (facing != 0)
|
||||
{
|
||||
world.checkShellCollide(this);
|
||||
}
|
||||
|
||||
xFlipPic = facing == -1;
|
||||
|
||||
runTime += (Math.abs(xa)) + 5;
|
||||
|
||||
xPic = (anim / 2) % 4 + 3;
|
||||
|
||||
|
||||
|
||||
if (!move(xa, 0))
|
||||
{
|
||||
world.sound.play(Art.samples[Art.SAMPLE_SHELL_BUMP], this, 1, 1, 1);
|
||||
|
||||
facing = -facing;
|
||||
}
|
||||
onGround = false;
|
||||
move(0, ya);
|
||||
|
||||
ya *= 0.85f;
|
||||
if (onGround)
|
||||
{
|
||||
xa *= GROUND_INERTIA;
|
||||
}
|
||||
else
|
||||
{
|
||||
xa *= AIR_INERTIA;
|
||||
}
|
||||
|
||||
if (!onGround)
|
||||
{
|
||||
ya += 2;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean move(float xa, float ya)
|
||||
{
|
||||
while (xa > 8)
|
||||
{
|
||||
if (!move(8, 0)) return false;
|
||||
xa -= 8;
|
||||
}
|
||||
while (xa < -8)
|
||||
{
|
||||
if (!move(-8, 0)) return false;
|
||||
xa += 8;
|
||||
}
|
||||
while (ya > 8)
|
||||
{
|
||||
if (!move(0, 8)) return false;
|
||||
ya -= 8;
|
||||
}
|
||||
while (ya < -8)
|
||||
{
|
||||
if (!move(0, -8)) return false;
|
||||
ya += 8;
|
||||
}
|
||||
|
||||
boolean collide = false;
|
||||
if (ya > 0)
|
||||
{
|
||||
if (isBlocking(x + xa - width, y + ya, xa, 0)) collide = true;
|
||||
else if (isBlocking(x + xa + width, y + ya, xa, 0)) collide = true;
|
||||
else if (isBlocking(x + xa - width, y + ya + 1, xa, ya)) collide = true;
|
||||
else if (isBlocking(x + xa + width, y + ya + 1, xa, ya)) collide = true;
|
||||
}
|
||||
if (ya < 0)
|
||||
{
|
||||
if (isBlocking(x + xa, y + ya - height, xa, ya)) collide = true;
|
||||
else if (collide || isBlocking(x + xa - width, y + ya - height, xa, ya)) collide = true;
|
||||
else if (collide || isBlocking(x + xa + width, y + ya - height, xa, ya)) collide = true;
|
||||
}
|
||||
if (xa > 0)
|
||||
{
|
||||
if (isBlocking(x + xa + width, y + ya - height, xa, ya)) collide = true;
|
||||
if (isBlocking(x + xa + width, y + ya - height / 2, xa, ya)) collide = true;
|
||||
if (isBlocking(x + xa + width, y + ya, xa, ya)) collide = true;
|
||||
|
||||
if (avoidCliffs && onGround && !world.level.isBlocking((int) ((x + xa + width) / 16), (int) ((y) / 16 + 1), xa, 1)) collide = true;
|
||||
}
|
||||
if (xa < 0)
|
||||
{
|
||||
if (isBlocking(x + xa - width, y + ya - height, xa, ya)) collide = true;
|
||||
if (isBlocking(x + xa - width, y + ya - height / 2, xa, ya)) collide = true;
|
||||
if (isBlocking(x + xa - width, y + ya, xa, ya)) collide = true;
|
||||
|
||||
if (avoidCliffs && onGround && !world.level.isBlocking((int) ((x + xa - width) / 16), (int) ((y) / 16 + 1), xa, 1)) collide = true;
|
||||
}
|
||||
|
||||
if (collide)
|
||||
{
|
||||
if (xa < 0)
|
||||
{
|
||||
x = (int) ((x - width) / 16) * 16 + width;
|
||||
this.xa = 0;
|
||||
}
|
||||
if (xa > 0)
|
||||
{
|
||||
x = (int) ((x + width) / 16 + 1) * 16 - width - 1;
|
||||
this.xa = 0;
|
||||
}
|
||||
if (ya < 0)
|
||||
{
|
||||
y = (int) ((y - height) / 16) * 16 + height;
|
||||
this.ya = 0;
|
||||
}
|
||||
if (ya > 0)
|
||||
{
|
||||
y = (int) (y / 16 + 1) * 16 - 1;
|
||||
onGround = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
x += xa;
|
||||
y += ya;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBlocking(float _x, float _y, float xa, float ya)
|
||||
{
|
||||
int x = (int) (_x / 16);
|
||||
int y = (int) (_y / 16);
|
||||
if (x == (int) (this.x / 16) && y == (int) (this.y / 16)) return false;
|
||||
|
||||
boolean blocking = world.level.isBlocking(x, y, xa, ya);
|
||||
|
||||
byte block = world.level.getBlock(x, y);
|
||||
|
||||
if (blocking && ya == 0 && xa!=0)
|
||||
{
|
||||
world.bump(x, y, true);
|
||||
}
|
||||
|
||||
return blocking;
|
||||
}
|
||||
|
||||
public void bumpCheck(int xTile, int yTile)
|
||||
{
|
||||
if (x + width > xTile * 16 && x - width < xTile * 16 + 16 && yTile == (int) ((y - 1) / 16))
|
||||
{
|
||||
facing = -world.mario.facing;
|
||||
ya = -10;
|
||||
}
|
||||
}
|
||||
|
||||
public void die()
|
||||
{
|
||||
dead = true;
|
||||
|
||||
carried = false;
|
||||
|
||||
xa = -facing * 2;
|
||||
ya = -5;
|
||||
deadTime = 100;
|
||||
|
||||
if(world.recorder != null)
|
||||
world.recorder.killRecord(this);
|
||||
}
|
||||
|
||||
public boolean shellCollideCheck(Shell shell)
|
||||
{
|
||||
if (deadTime != 0) return false;
|
||||
|
||||
float xD = shell.x - x;
|
||||
float yD = shell.y - y;
|
||||
|
||||
if (xD > -16 && xD < 16)
|
||||
{
|
||||
if (yD > -height && yD < shell.height)
|
||||
{
|
||||
world.sound.play(Art.samples[Art.SAMPLE_MARIO_KICK], this, 1, 1, 1);
|
||||
|
||||
if (world.mario.carried == shell || world.mario.carried == this)
|
||||
{
|
||||
world.mario.carried = null;
|
||||
}
|
||||
|
||||
die();
|
||||
shell.die();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public void release(Mario mario)
|
||||
{
|
||||
carried = false;
|
||||
facing = mario.facing;
|
||||
x += facing * 8;
|
||||
}
|
||||
}
|
||||
46
src/dk/itu/mario/engine/sprites/Sparkle.java
Normal file
46
src/dk/itu/mario/engine/sprites/Sparkle.java
Normal file
@@ -0,0 +1,46 @@
|
||||
package dk.itu.mario.engine.sprites;
|
||||
|
||||
import dk.itu.mario.engine.Art;
|
||||
|
||||
|
||||
public class Sparkle extends Sprite
|
||||
{
|
||||
public int life;
|
||||
public int xPicStart;
|
||||
|
||||
public Sparkle(int x, int y, float xa, float ya)
|
||||
{
|
||||
this(x, y, xa, ya, (int)(Math.random()*2), 0, 5);
|
||||
}
|
||||
|
||||
public Sparkle(int x, int y, float xa, float ya, int xPic, int yPic, int timeSpan)
|
||||
{
|
||||
sheet = Art.particles;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.xa = xa;
|
||||
this.ya = ya;
|
||||
this.xPic = xPic;
|
||||
xPicStart = xPic;
|
||||
this.yPic = yPic;
|
||||
this.xPicO = 4;
|
||||
this.yPicO = 4;
|
||||
|
||||
wPic = 8;
|
||||
hPic = 8;
|
||||
life = 10+(int)(Math.random()*timeSpan);
|
||||
}
|
||||
|
||||
public void move()
|
||||
{
|
||||
if (life>10)
|
||||
xPic = 7;
|
||||
else
|
||||
xPic = xPicStart+(10-life)*4/10;
|
||||
|
||||
if (life--<0) Sprite.spriteContext.removeSprite(this);
|
||||
|
||||
x+=xa;
|
||||
y+=ya;
|
||||
}
|
||||
}
|
||||
117
src/dk/itu/mario/engine/sprites/Sprite.java
Normal file
117
src/dk/itu/mario/engine/sprites/Sprite.java
Normal file
@@ -0,0 +1,117 @@
|
||||
package dk.itu.mario.engine.sprites;
|
||||
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Image;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
import dk.itu.mario.engine.sonar.SoundSource;
|
||||
|
||||
public class Sprite implements SoundSource
|
||||
{
|
||||
public static SpriteContext spriteContext;
|
||||
|
||||
public float xOld, yOld, x, y, xa, ya;
|
||||
|
||||
public int xPic, yPic;
|
||||
public int wPic = 32;
|
||||
public int hPic = 32;
|
||||
public int xPicO, yPicO;
|
||||
public boolean xFlipPic = false;
|
||||
public boolean yFlipPic = false;
|
||||
public Image[][] sheet;
|
||||
public boolean visible = true;
|
||||
|
||||
public int layer = 1;
|
||||
|
||||
public SpriteTemplate spriteTemplate;
|
||||
|
||||
public void move()
|
||||
{
|
||||
x+=xa;
|
||||
y+=ya;
|
||||
}
|
||||
|
||||
public void render(Graphics og, float alpha)
|
||||
{
|
||||
if (!visible) return;
|
||||
|
||||
int xPixel = (int)(xOld+(x-xOld)*alpha)-xPicO;
|
||||
int yPixel = (int)(yOld+(y-yOld)*alpha)-yPicO;
|
||||
|
||||
og.drawImage(sheet[xPic][yPic], xPixel+(xFlipPic?wPic:0), yPixel+(yFlipPic?hPic:0), xFlipPic?-wPic:wPic, yFlipPic?-hPic:hPic, null);
|
||||
}
|
||||
|
||||
/* private void blit(Graphics og, Image bitmap, int x0, int y0, int x1, int y1, int w, int h)
|
||||
{
|
||||
if (!xFlipPic)
|
||||
{
|
||||
if (!yFlipPic)
|
||||
{
|
||||
og.drawImage(bitmap, x0, y0, x0+w, y0+h, x1, y1, x1+w, y1+h, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
og.drawImage(bitmap, x0, y0, x0+w, y0+h, x1, y1+h, x1+w, y1, null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!yFlipPic)
|
||||
{
|
||||
og.drawImage(bitmap, x0, y0, x0+w, y0+h, x1+w, y1, x1, y1+h, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
og.drawImage(bitmap, x0, y0, x0+w, y0+h, x1+w, y1+h, x1, y1, null);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
public final void tick()
|
||||
{
|
||||
xOld = x;
|
||||
yOld = y;
|
||||
move();
|
||||
}
|
||||
|
||||
public final void tickNoMove()
|
||||
{
|
||||
xOld = x;
|
||||
yOld = y;
|
||||
}
|
||||
|
||||
public float getX(float alpha)
|
||||
{
|
||||
return (xOld+(x-xOld)*alpha)-xPicO;
|
||||
}
|
||||
|
||||
public float getY(float alpha)
|
||||
{
|
||||
return (yOld+(y-yOld)*alpha)-yPicO;
|
||||
}
|
||||
|
||||
public void collideCheck()
|
||||
{
|
||||
}
|
||||
|
||||
public void bumpCheck(int xTile, int yTile)
|
||||
{
|
||||
}
|
||||
|
||||
public boolean shellCollideCheck(Shell shell)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void release(Mario mario)
|
||||
{
|
||||
}
|
||||
|
||||
public boolean fireballCollideCheck(Fireball fireball)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
18
src/dk/itu/mario/engine/sprites/SpriteContext.java
Normal file
18
src/dk/itu/mario/engine/sprites/SpriteContext.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package dk.itu.mario.engine.sprites;
|
||||
|
||||
/**
|
||||
* <p>Title: </p>
|
||||
*
|
||||
* <p>Description: </p>
|
||||
*
|
||||
* <p>Copyright: Copyright (c) 2010</p>
|
||||
*
|
||||
* <p>Company: </p>
|
||||
*
|
||||
* @author not attributable
|
||||
* @version 1.0
|
||||
*/
|
||||
public interface SpriteContext {
|
||||
public void addSprite(Sprite sprite);
|
||||
public void removeSprite(Sprite sprite);
|
||||
}
|
||||
60
src/dk/itu/mario/engine/sprites/SpriteTemplate.java
Normal file
60
src/dk/itu/mario/engine/sprites/SpriteTemplate.java
Normal file
@@ -0,0 +1,60 @@
|
||||
package dk.itu.mario.engine.sprites;
|
||||
|
||||
import dk.itu.mario.scene.LevelScene;
|
||||
|
||||
public class SpriteTemplate
|
||||
{
|
||||
public static final int RED_TURTLE = 0;
|
||||
public static final int GREEN_TURTLE = 1;
|
||||
public static final int GOOMPA = 2;
|
||||
public static final int ARMORED_TURTLE = 3;
|
||||
public static final int JUMP_FLOWER = 4;
|
||||
public static final int CANNON_BALL = 5;
|
||||
public static final int CHOMP_FLOWER = 6;
|
||||
|
||||
public static int enemiesSpawned = 0;
|
||||
public static int enemiesMax = 1000;
|
||||
|
||||
public boolean hasSpawned = false;
|
||||
|
||||
public int lastVisibleTick = -1;
|
||||
public Sprite sprite;
|
||||
public boolean isDead = false;
|
||||
private boolean winged;
|
||||
|
||||
public int type;
|
||||
public int direction = 1;
|
||||
|
||||
public SpriteTemplate(int type, boolean winged)
|
||||
{
|
||||
this.type = type;
|
||||
this.winged = winged;
|
||||
}
|
||||
|
||||
public void spawn(LevelScene world, int x, int y, int dir)
|
||||
{
|
||||
if (isDead || enemiesSpawned >= enemiesMax) return;
|
||||
|
||||
if (type==Enemy.ENEMY_FLOWER)
|
||||
{
|
||||
sprite = new FlowerEnemy(world, x*16+15, y*16+24);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite = new Enemy(world, x*16+8, y*16+15, dir, type, winged);
|
||||
}
|
||||
|
||||
//correct for flipping
|
||||
if(direction == -1){
|
||||
sprite.x -= 14;
|
||||
}
|
||||
|
||||
sprite.spriteTemplate = this;
|
||||
world.addSprite(sprite);
|
||||
|
||||
if(!hasSpawned)
|
||||
enemiesSpawned++;
|
||||
|
||||
hasSpawned = true;
|
||||
}
|
||||
}
|
||||
BIN
src/dk/itu/mario/engine/util/.DS_Store
vendored
Normal file
BIN
src/dk/itu/mario/engine/util/.DS_Store
vendored
Normal file
Binary file not shown.
37
src/dk/itu/mario/engine/util/FileHandler.java
Normal file
37
src/dk/itu/mario/engine/util/FileHandler.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package dk.itu.mario.engine.util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
|
||||
public class FileHandler {
|
||||
|
||||
public static String readFile(String fileName){
|
||||
String info = "";
|
||||
try {
|
||||
FileReader input = new FileReader(fileName);
|
||||
BufferedReader bufRead = new BufferedReader(input);
|
||||
|
||||
String line;
|
||||
|
||||
int count = 0;
|
||||
line = bufRead.readLine();
|
||||
info = line +"\n";
|
||||
count++;
|
||||
|
||||
|
||||
while (line != null){
|
||||
// System.out.println(count+": "+line);
|
||||
line = bufRead.readLine();
|
||||
info += line + "\n";
|
||||
count++;
|
||||
}
|
||||
|
||||
bufRead.close();
|
||||
|
||||
}catch (Exception e){
|
||||
// If another exception is generated, print a stack trace
|
||||
e.printStackTrace();
|
||||
}
|
||||
return info;
|
||||
}
|
||||
}
|
||||
22
src/dk/itu/mario/engine/util/UIItem.java
Normal file
22
src/dk/itu/mario/engine/util/UIItem.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package dk.itu.mario.engine.util;
|
||||
|
||||
import java.awt.Graphics;
|
||||
|
||||
public abstract class UIItem{
|
||||
|
||||
protected int x,y;
|
||||
protected boolean selected;
|
||||
protected int width,height;
|
||||
|
||||
public abstract void render(Graphics g);
|
||||
public abstract void prev();
|
||||
public abstract void next();
|
||||
|
||||
public void setSelected(){
|
||||
selected = true;
|
||||
}
|
||||
|
||||
public void setUnselected(){
|
||||
selected = false;
|
||||
}
|
||||
}
|
||||
83
src/dk/itu/mario/engine/util/UITextArea.java
Normal file
83
src/dk/itu/mario/engine/util/UITextArea.java
Normal file
@@ -0,0 +1,83 @@
|
||||
package dk.itu.mario.engine.util;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class UITextArea extends UIItem{
|
||||
|
||||
protected String text;
|
||||
protected int width, height;
|
||||
protected Font font;
|
||||
protected ArrayList<String> lines = new ArrayList<String>();
|
||||
|
||||
public static boolean showBox = false;
|
||||
|
||||
public UITextArea(String text, Font font, int x, int y, int width){
|
||||
this.text = text;
|
||||
this.font = font;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
public void next() {
|
||||
}
|
||||
|
||||
public void prev() {
|
||||
}
|
||||
|
||||
public void render(Graphics g) {
|
||||
Graphics2D g2 = (Graphics2D)g;
|
||||
|
||||
g.setFont(font);
|
||||
|
||||
lines.clear();
|
||||
|
||||
Rectangle2D rec = font.getStringBounds(text,g2.getFontRenderContext());
|
||||
|
||||
String tempText = new String();
|
||||
|
||||
if(rec.getWidth()>width){
|
||||
for(int i=0;i<text.length();++i){
|
||||
tempText += text.charAt(i);
|
||||
|
||||
rec = font.getStringBounds(tempText+"A",g2.getFontRenderContext());
|
||||
|
||||
if(rec.getWidth()>=width){
|
||||
lines.add(tempText);
|
||||
tempText = new String();
|
||||
}
|
||||
}
|
||||
|
||||
lines.add(tempText);
|
||||
}
|
||||
else{
|
||||
lines.add(text);
|
||||
}
|
||||
|
||||
for(int j=0;j<lines.size();++j){
|
||||
rec = font.getStringBounds(lines.get(j),g2.getFontRenderContext());
|
||||
g.drawString(lines.get(j),x,y+(int)rec.getHeight()*(j+1));
|
||||
}
|
||||
|
||||
if(showBox){
|
||||
height = (int)rec.getHeight()*lines.size();
|
||||
g.setColor(Color.BLUE);
|
||||
g.drawRect(x,y,width,height);
|
||||
}
|
||||
}
|
||||
|
||||
public int getWidth(){
|
||||
return width;
|
||||
}
|
||||
|
||||
public int getHeight(){
|
||||
return height;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
BIN
src/dk/itu/mario/level/.DS_Store
vendored
Normal file
BIN
src/dk/itu/mario/level/.DS_Store
vendored
Normal file
Binary file not shown.
170
src/dk/itu/mario/level/BgLevelGenerator.java
Normal file
170
src/dk/itu/mario/level/BgLevelGenerator.java
Normal file
@@ -0,0 +1,170 @@
|
||||
package dk.itu.mario.level;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import dk.itu.mario.MarioInterface.LevelInterface;
|
||||
|
||||
public class BgLevelGenerator {
|
||||
private static Random levelSeedRandom = new Random();
|
||||
|
||||
public static Level createLevel(int width, int height, boolean distant,
|
||||
int type) {
|
||||
BgLevelGenerator levelGenerator = new BgLevelGenerator(width, height,
|
||||
distant, type);
|
||||
return levelGenerator.createLevel(levelSeedRandom.nextLong());
|
||||
}
|
||||
|
||||
private int width;
|
||||
private int height;
|
||||
private boolean distant;
|
||||
private int type;
|
||||
|
||||
private BgLevelGenerator(int width, int height, boolean distant, int type) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.distant = distant;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
private Level createLevel(long seed) {
|
||||
Level level = new Level(width, height);
|
||||
Random random = new Random(seed);
|
||||
|
||||
switch (type) {
|
||||
case LevelInterface.TYPE_OVERGROUND: {
|
||||
|
||||
int range = distant ? 4 : 6;
|
||||
int offs = distant ? 2 : 1;
|
||||
int oh = random.nextInt(range) + offs;
|
||||
int h = random.nextInt(range) + offs;
|
||||
for (int x = 0; x < width; x++) {
|
||||
oh = h;
|
||||
while (oh == h) {
|
||||
h = random.nextInt(range) + offs;
|
||||
}
|
||||
for (int y = 0; y < height; y++) {
|
||||
int h0 = (oh < h) ? oh : h;
|
||||
int h1 = (oh < h) ? h : oh;
|
||||
if (y < h0) {
|
||||
if (distant) {
|
||||
int s = 2;
|
||||
if (y < 2)
|
||||
s = y;
|
||||
level.setBlock(x, y, (byte) (4 + s * 8));
|
||||
} else {
|
||||
level.setBlock(x, y, (byte) 5);
|
||||
}
|
||||
} else if (y == h0) {
|
||||
int s = h0 == h ? 0 : 1;
|
||||
s += distant ? 2 : 0;
|
||||
level.setBlock(x, y, (byte) s);
|
||||
} else if (y == h1) {
|
||||
int s = h0 == h ? 0 : 1;
|
||||
s += distant ? 2 : 0;
|
||||
level.setBlock(x, y, (byte) (s + 16));
|
||||
} else {
|
||||
int s = y > h1 ? 1 : 0;
|
||||
if (h0 == oh)
|
||||
s = 1 - s;
|
||||
s += distant ? 2 : 0;
|
||||
level.setBlock(x, y, (byte) (s + 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LevelInterface.TYPE_UNDERGROUND: {
|
||||
if (distant) {
|
||||
int tt = 0;
|
||||
for (int x = 0; x < width; x++) {
|
||||
if (random.nextDouble() < 0.75)
|
||||
tt = 1 - tt;
|
||||
for (int y = 0; y < height; y++) {
|
||||
int t = tt;
|
||||
int yy = y - 2;
|
||||
if (yy < 0 || yy > 4) {
|
||||
yy = 2;
|
||||
t = 0;
|
||||
}
|
||||
level.setBlock(x, y, (byte) (4 + t + (3 + yy) * 8));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
int t = x % 2;
|
||||
int yy = y - 1;
|
||||
if (yy < 0 || yy > 7) {
|
||||
yy = 7;
|
||||
t = 0;
|
||||
}
|
||||
if (t == 0 && yy > 1 && yy < 5) {
|
||||
t = -1;
|
||||
yy = 0;
|
||||
}
|
||||
level.setBlock(x, y, (byte) (6 + t + (yy) * 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LevelInterface.TYPE_CASTLE: {
|
||||
if (distant) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
int t = x % 2;
|
||||
int yy = y - 1;
|
||||
if (yy > 2 && yy < 5) {
|
||||
yy = 2;
|
||||
} else if (yy >= 5) {
|
||||
yy -= 2;
|
||||
}
|
||||
if (yy < 0) {
|
||||
t = 0;
|
||||
yy = 5;
|
||||
} else if (yy > 4) {
|
||||
t = 1;
|
||||
yy = 5;
|
||||
} else if (t < 1 && yy == 3) {
|
||||
t = 0;
|
||||
yy = 3;
|
||||
} else if (t < 1 && yy > 0 && yy < 3) {
|
||||
t = 0;
|
||||
yy = 2;
|
||||
}
|
||||
level.setBlock(x, y, (byte) (1 + t + (yy + 4) * 8));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
int t = x % 3;
|
||||
int yy = y - 1;
|
||||
if (yy > 2 && yy < 5) {
|
||||
yy = 2;
|
||||
} else if (yy >= 5) {
|
||||
yy -= 2;
|
||||
}
|
||||
if (yy < 0) {
|
||||
t = 1;
|
||||
yy = 5;
|
||||
} else if (yy > 4) {
|
||||
t = 2;
|
||||
yy = 5;
|
||||
} else if (t < 2 && yy == 4) {
|
||||
t = 2;
|
||||
yy = 4;
|
||||
} else if (t < 2 && yy > 0 && yy < 4) {
|
||||
t = 4;
|
||||
yy = -3;
|
||||
}
|
||||
level.setBlock(x, y, (byte) (1 + t + (yy + 3) * 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return level;
|
||||
}
|
||||
}
|
||||
563
src/dk/itu/mario/level/CustomizedLevel.java
Normal file
563
src/dk/itu/mario/level/CustomizedLevel.java
Normal file
@@ -0,0 +1,563 @@
|
||||
package dk.itu.mario.level;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import dk.itu.mario.MarioInterface.Constraints;
|
||||
import dk.itu.mario.MarioInterface.GamePlay;
|
||||
import dk.itu.mario.MarioInterface.LevelInterface;
|
||||
import dk.itu.mario.engine.sprites.Enemy;
|
||||
import dk.itu.mario.engine.sprites.SpriteTemplate;
|
||||
|
||||
public class CustomizedLevel extends Level implements LevelInterface {
|
||||
|
||||
Random random;
|
||||
|
||||
private static final int ODDS_STRAIGHT = 0;
|
||||
private static final int ODDS_HILL_STRAIGHT = 1;
|
||||
private static final int ODDS_TUBES = 2;
|
||||
private static final int ODDS_JUMP = 3;
|
||||
private static final int ODDS_CANNONS = 4;
|
||||
private static final int JumpingThreshold = 3;
|
||||
|
||||
private int[] odds = new int[5];
|
||||
private int totalOdds;
|
||||
|
||||
private int difficulty;
|
||||
private int type;
|
||||
private int gaps;
|
||||
private int turtles;
|
||||
private int coins;
|
||||
|
||||
private GamePlay playerM;
|
||||
|
||||
public CustomizedLevel(int width, int height, long seed, int difficulty,
|
||||
int type, GamePlay playerMetrics) {
|
||||
super(width, height);
|
||||
this.playerM = playerMetrics;
|
||||
creat(seed, difficulty, type);
|
||||
}
|
||||
|
||||
public void creat(long seed, int difficulty, int type) {
|
||||
this.type = type;
|
||||
this.difficulty = difficulty;
|
||||
odds[ODDS_STRAIGHT] = 30;
|
||||
odds[ODDS_HILL_STRAIGHT] = 20;
|
||||
odds[ODDS_TUBES] = 2 + 2 * difficulty;
|
||||
int jumpDifficulty = 1;
|
||||
// adapt the game so that it has a number of gaps proportional to the
|
||||
// number of jumps the player made in the test level. The more the
|
||||
// jumps,
|
||||
// the more the gaps.
|
||||
if (playerM.jumpsNumber > JumpingThreshold)
|
||||
jumpDifficulty = 2;
|
||||
odds[ODDS_JUMP] = jumpDifficulty;
|
||||
odds[ODDS_CANNONS] = -10 + 5 * difficulty;
|
||||
|
||||
if (type != LevelInterface.TYPE_OVERGROUND) {
|
||||
odds[ODDS_HILL_STRAIGHT] = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < odds.length; i++) {
|
||||
// failsafe (no negative odds)
|
||||
if (odds[i] < 0) {
|
||||
odds[i] = 0;
|
||||
}
|
||||
|
||||
totalOdds += odds[i];
|
||||
odds[i] = totalOdds - odds[i];
|
||||
}
|
||||
|
||||
random = new Random(seed);
|
||||
|
||||
// create the start location
|
||||
int length = 0;
|
||||
length += buildStraight(0, getWidth(), true);
|
||||
|
||||
// create all of the medium sections
|
||||
while (length < getWidth() - 64) {
|
||||
length += buildZone(length, getWidth() - length);
|
||||
}
|
||||
|
||||
// set the end piece
|
||||
int floor = height - 1 - random.nextInt(4);
|
||||
|
||||
// create the exit
|
||||
xExit = length + 8;
|
||||
yExit = floor;
|
||||
|
||||
for (int x = length; x < getWidth(); x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
if (y >= floor) {
|
||||
setBlock(x, y, Level.GROUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type == LevelInterface.TYPE_CASTLE
|
||||
|| type == LevelInterface.TYPE_UNDERGROUND) {
|
||||
int ceiling = 0;
|
||||
int run = 0;
|
||||
for (int x = 0; x < width; x++) {
|
||||
if (run-- <= 0 && x > 4) {
|
||||
ceiling = random.nextInt(4);
|
||||
run = random.nextInt(4) + 4;
|
||||
}
|
||||
for (int y = 0; y < height; y++) {
|
||||
if ((x > 4 && y <= ceiling) || x < 1) {
|
||||
setBlock(x, y, GROUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fixWalls();
|
||||
|
||||
}
|
||||
|
||||
private int buildZone(int x, int maxLength) {
|
||||
int t = random.nextInt(totalOdds);
|
||||
int type = 0;
|
||||
|
||||
for (int i = 0; i < odds.length; i++) {
|
||||
if (odds[ODDS_JUMP] <= t * 2 + 30) {
|
||||
type = ODDS_JUMP;
|
||||
break;
|
||||
}
|
||||
if (odds[i] <= t) {
|
||||
type = i;
|
||||
}
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case ODDS_STRAIGHT:
|
||||
return buildStraight(x, maxLength, false);
|
||||
case ODDS_HILL_STRAIGHT:
|
||||
return buildHillStraight(x, maxLength);
|
||||
case ODDS_TUBES:
|
||||
return buildTubes(x, maxLength);
|
||||
case ODDS_JUMP:
|
||||
if (gaps < Constraints.gaps)
|
||||
return buildJump(x, maxLength);
|
||||
else
|
||||
return buildStraight(x, maxLength, false);
|
||||
case ODDS_CANNONS:
|
||||
return buildCannons(x, maxLength);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int buildJump(int xo, int maxLength) {
|
||||
gaps++;
|
||||
// jl: jump length
|
||||
// js: the number of blocks that are available at either side for free
|
||||
int js = random.nextInt(4) + 2;
|
||||
int jl = random.nextInt(2) + 2;
|
||||
int length = js * 2 + jl;
|
||||
|
||||
boolean hasStairs = random.nextInt(3) == 0;
|
||||
|
||||
int floor = height - 1 - random.nextInt(4);
|
||||
// run for the from the start x position, for the whole length
|
||||
for (int x = xo; x < xo + length; x++) {
|
||||
if (x < xo + js || x > xo + length - js - 1) {
|
||||
// run for all y's since we need to paint blocks upward
|
||||
for (int y = 0; y < height; y++) { // paint ground up until the
|
||||
// floor
|
||||
if (y >= floor) {
|
||||
setBlock(x, y, GROUND);
|
||||
}
|
||||
// if it is above ground, start making stairs of rocks
|
||||
else if (hasStairs) { // LEFT SIDE
|
||||
if (x < xo + js) { // we need to max it out and level
|
||||
// because it wont
|
||||
// paint ground correctly unless two bricks are side
|
||||
// by side
|
||||
if (y >= floor - (x - xo) + 1) {
|
||||
setBlock(x, y, ROCK);
|
||||
}
|
||||
} else { // RIGHT SIDE
|
||||
if (y >= floor - ((xo + length) - x) + 2) {
|
||||
setBlock(x, y, ROCK);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
private int buildCannons(int xo, int maxLength) {
|
||||
int length = random.nextInt(10) + 2;
|
||||
if (length > maxLength)
|
||||
length = maxLength;
|
||||
|
||||
int floor = height - 1 - random.nextInt(4);
|
||||
int xCannon = xo + 1 + random.nextInt(4);
|
||||
for (int x = xo; x < xo + length; x++) {
|
||||
if (x > xCannon) {
|
||||
xCannon += 2 + random.nextInt(4);
|
||||
}
|
||||
if (xCannon == xo + length - 1)
|
||||
xCannon += 10;
|
||||
int cannonHeight = floor - random.nextInt(4) - 1;
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
if (y >= floor) {
|
||||
setBlock(x, y, (byte) (1 + 9 * 16));
|
||||
} else {
|
||||
if (x == xCannon && y >= cannonHeight) {
|
||||
if (y == cannonHeight) {
|
||||
setBlock(x, y, (byte) (14 + 0 * 16));
|
||||
} else if (y == cannonHeight + 1) {
|
||||
setBlock(x, y, (byte) (14 + 1 * 16));
|
||||
} else {
|
||||
setBlock(x, y, (byte) (14 + 2 * 16));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
private int buildHillStraight(int xo, int maxLength) {
|
||||
int length = random.nextInt(10) + 10;
|
||||
if (length > maxLength)
|
||||
length = maxLength;
|
||||
|
||||
int floor = height - 1 - random.nextInt(4);
|
||||
for (int x = xo; x < xo + length; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
if (y >= floor) {
|
||||
setBlock(x, y, Level.GROUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addEnemyLine(xo + 1, xo + length - 1, floor - 1);
|
||||
|
||||
int h = floor;
|
||||
|
||||
boolean keepGoing = true;
|
||||
|
||||
boolean[] occupied = new boolean[length];
|
||||
while (keepGoing) {
|
||||
h = h - 2 - random.nextInt(3);
|
||||
|
||||
if (h <= 0) {
|
||||
keepGoing = false;
|
||||
} else {
|
||||
int l = random.nextInt(5) + 3;
|
||||
int xxo = random.nextInt(length - l - 2) + xo + 1;
|
||||
|
||||
if (occupied[xxo - xo] || occupied[xxo - xo + l]
|
||||
|| occupied[xxo - xo - 1] || occupied[xxo - xo + l + 1]) {
|
||||
keepGoing = false;
|
||||
} else {
|
||||
occupied[xxo - xo] = true;
|
||||
occupied[xxo - xo + l] = true;
|
||||
addEnemyLine(xxo, xxo + l, h - 1);
|
||||
if (random.nextInt(4) == 0) {
|
||||
decorate(xxo - 1, xxo + l + 1, h);
|
||||
keepGoing = false;
|
||||
}
|
||||
for (int x = xxo; x < xxo + l; x++) {
|
||||
for (int y = h; y < floor; y++) {
|
||||
int xx = 5;
|
||||
if (x == xxo)
|
||||
xx = 4;
|
||||
if (x == xxo + l - 1)
|
||||
xx = 6;
|
||||
int yy = 9;
|
||||
if (y == h)
|
||||
yy = 8;
|
||||
|
||||
if (getBlock(x, y) == 0) {
|
||||
setBlock(x, y, (byte) (xx + yy * 16));
|
||||
} else {
|
||||
if (getBlock(x, y) == Level.HILL_TOP_LEFT)
|
||||
setBlock(x, y, Level.HILL_TOP_LEFT_IN);
|
||||
if (getBlock(x, y) == Level.HILL_TOP_RIGHT)
|
||||
setBlock(x, y, Level.HILL_TOP_RIGHT_IN);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
private void addEnemyLine(int x0, int x1, int y) {
|
||||
for (int x = x0; x < x1; x++) {
|
||||
if (random.nextInt(50) < 25) {
|
||||
int type = random.nextInt(4);
|
||||
|
||||
type = random.nextInt(3);
|
||||
if (turtles < Constraints.turtels) {
|
||||
if (type == Enemy.ENEMY_GREEN_KOOPA
|
||||
|| type == Enemy.ENEMY_RED_KOOPA) {
|
||||
turtles++;
|
||||
setSpriteTemplate(x, y,
|
||||
new SpriteTemplate(type,
|
||||
random.nextInt(35) < difficulty));
|
||||
} else {
|
||||
setSpriteTemplate(x, y,
|
||||
new SpriteTemplate(type,
|
||||
random.nextInt(35) < difficulty));
|
||||
}
|
||||
} else {
|
||||
setSpriteTemplate(
|
||||
x,
|
||||
y,
|
||||
new SpriteTemplate(Enemy.ENEMY_GOOMBA, random
|
||||
.nextInt(35) < difficulty));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int buildTubes(int xo, int maxLength) {
|
||||
int length = random.nextInt(10) + 5;
|
||||
if (length > maxLength)
|
||||
length = maxLength;
|
||||
|
||||
int floor = height - 1 - random.nextInt(4);
|
||||
int xTube = xo + 1 + random.nextInt(4);
|
||||
int tubeHeight = floor - random.nextInt(2) - 2;
|
||||
for (int x = xo; x < xo + length; x++) {
|
||||
if (x > xTube + 1) {
|
||||
xTube += 3 + random.nextInt(4);
|
||||
tubeHeight = floor - random.nextInt(2) - 2;
|
||||
}
|
||||
if (xTube >= xo + length - 2)
|
||||
xTube += 10;
|
||||
|
||||
if (x == xTube && random.nextInt(11) < difficulty + 1) {
|
||||
setSpriteTemplate(x, tubeHeight, new SpriteTemplate(
|
||||
Enemy.ENEMY_FLOWER, false));
|
||||
}
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
if (y >= floor) {
|
||||
setBlock(x, y, (byte) (1 + 9 * 16));
|
||||
|
||||
} else {
|
||||
if ((x == xTube || x == xTube + 1) && y >= tubeHeight) {
|
||||
int xPic = 10 + x - xTube;
|
||||
|
||||
if (y == tubeHeight) {
|
||||
// tube top
|
||||
setBlock(x, y, (byte) (xPic + 0 * 16));
|
||||
} else {
|
||||
// tube side
|
||||
setBlock(x, y, (byte) (xPic + 1 * 16));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
private int buildStraight(int xo, int maxLength, boolean safe) {
|
||||
int length = random.nextInt(10) + 2;
|
||||
|
||||
if (safe)
|
||||
length = 10 + random.nextInt(5);
|
||||
|
||||
if (length > maxLength)
|
||||
length = maxLength;
|
||||
|
||||
int floor = height - 1 - random.nextInt(4);
|
||||
|
||||
// runs from the specified x position to the length of the segment
|
||||
for (int x = xo; x < xo + length; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
if (y >= floor) {
|
||||
setBlock(x, y, Level.GROUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!safe) {
|
||||
if (length > 5) {
|
||||
decorate(xo, xo + length, floor);
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
private void decorate(int xStart, int xLength, int floor) {
|
||||
// if its at the very top, just return
|
||||
if (floor < 1)
|
||||
return;
|
||||
boolean rocks = true;
|
||||
|
||||
// add an enemy line above the box
|
||||
addEnemyLine(xStart + 1, xLength - 1, floor - 1);
|
||||
|
||||
int s = random.nextInt(4);
|
||||
int e = random.nextInt(4);
|
||||
|
||||
if (floor - 2 > 0) {
|
||||
if ((xLength - 1 - e) - (xStart + 1 + s) > 1) {
|
||||
for (int x = xStart + 1 + s; x < xLength - 1 - e; x++) {
|
||||
setBlock(x, floor - 2, (byte) (2 + 2 * 16));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s = random.nextInt(4);
|
||||
e = random.nextInt(4);
|
||||
|
||||
if (floor - 4 > 0) {
|
||||
if ((xLength - 1 - e) - (xStart + 1 + s) > 2) {
|
||||
for (int x = xStart + 1 + s; x < xLength - 1 - e; x++) {
|
||||
if (rocks) {
|
||||
if (x != xStart + 1 && x != xLength - 2
|
||||
&& random.nextInt(2) == 0) {
|
||||
if (random.nextInt(2) == 0) {
|
||||
setBlock(x, floor - 4, BLOCK_POWERUP);
|
||||
} else {
|
||||
if (coins < Constraints.coinBlocks) {
|
||||
coins++;
|
||||
setBlock(x, floor - 4, BLOCK_COIN);
|
||||
} else {
|
||||
setBlock(x, floor - 4, BLOCK_EMPTY);
|
||||
}
|
||||
}
|
||||
} else if (random.nextInt(4) == 0) {
|
||||
if (random.nextInt(4) == 0) {
|
||||
setBlock(x, floor - 4, (byte) (2 + 1 * 16));
|
||||
} else {
|
||||
setBlock(x, floor - 4, (byte) (1 + 1 * 16));
|
||||
}
|
||||
} else {
|
||||
setBlock(x, floor - 4, BLOCK_EMPTY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fixWalls() {
|
||||
boolean[][] blockMap = new boolean[width + 1][height + 1];
|
||||
|
||||
for (int x = 0; x < width + 1; x++) {
|
||||
for (int y = 0; y < height + 1; y++) {
|
||||
int blocks = 0;
|
||||
for (int xx = x - 1; xx < x + 1; xx++) {
|
||||
for (int yy = y - 1; yy < y + 1; yy++) {
|
||||
if (getBlockCapped(xx, yy) == GROUND) {
|
||||
blocks++;
|
||||
}
|
||||
}
|
||||
}
|
||||
blockMap[x][y] = blocks == 4;
|
||||
}
|
||||
}
|
||||
blockify(this, blockMap, width + 1, height + 1);
|
||||
}
|
||||
|
||||
private void blockify(Level level, boolean[][] blocks, int width, int height) {
|
||||
int to = 0;
|
||||
if (type == LevelInterface.TYPE_CASTLE) {
|
||||
to = 4 * 2;
|
||||
} else if (type == LevelInterface.TYPE_UNDERGROUND) {
|
||||
to = 4 * 3;
|
||||
}
|
||||
|
||||
boolean[][] b = new boolean[2][2];
|
||||
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int xx = x; xx <= x + 1; xx++) {
|
||||
for (int yy = y; yy <= y + 1; yy++) {
|
||||
int _xx = xx;
|
||||
int _yy = yy;
|
||||
if (_xx < 0)
|
||||
_xx = 0;
|
||||
if (_yy < 0)
|
||||
_yy = 0;
|
||||
if (_xx > width - 1)
|
||||
_xx = width - 1;
|
||||
if (_yy > height - 1)
|
||||
_yy = height - 1;
|
||||
b[xx - x][yy - y] = blocks[_xx][_yy];
|
||||
}
|
||||
}
|
||||
|
||||
if (b[0][0] == b[1][0] && b[0][1] == b[1][1]) {
|
||||
if (b[0][0] == b[0][1]) {
|
||||
if (b[0][0]) {
|
||||
level.setBlock(x, y, (byte) (1 + 9 * 16 + to));
|
||||
} else {
|
||||
// KEEP OLD BLOCK!
|
||||
}
|
||||
} else {
|
||||
if (b[0][0]) {
|
||||
// down grass top?
|
||||
level.setBlock(x, y, (byte) (1 + 10 * 16 + to));
|
||||
} else {
|
||||
// up grass top
|
||||
level.setBlock(x, y, (byte) (1 + 8 * 16 + to));
|
||||
}
|
||||
}
|
||||
} else if (b[0][0] == b[0][1] && b[1][0] == b[1][1]) {
|
||||
if (b[0][0]) {
|
||||
// right grass top
|
||||
level.setBlock(x, y, (byte) (2 + 9 * 16 + to));
|
||||
} else {
|
||||
// left grass top
|
||||
level.setBlock(x, y, (byte) (0 + 9 * 16 + to));
|
||||
}
|
||||
} else if (b[0][0] == b[1][1] && b[0][1] == b[1][0]) {
|
||||
level.setBlock(x, y, (byte) (1 + 9 * 16 + to));
|
||||
} else if (b[0][0] == b[1][0]) {
|
||||
if (b[0][0]) {
|
||||
if (b[0][1]) {
|
||||
level.setBlock(x, y, (byte) (3 + 10 * 16 + to));
|
||||
} else {
|
||||
level.setBlock(x, y, (byte) (3 + 11 * 16 + to));
|
||||
}
|
||||
} else {
|
||||
if (b[0][1]) {
|
||||
// right up grass top
|
||||
level.setBlock(x, y, (byte) (2 + 8 * 16 + to));
|
||||
} else {
|
||||
// left up grass top
|
||||
level.setBlock(x, y, (byte) (0 + 8 * 16 + to));
|
||||
}
|
||||
}
|
||||
} else if (b[0][1] == b[1][1]) {
|
||||
if (b[0][1]) {
|
||||
if (b[0][0]) {
|
||||
// left pocket grass
|
||||
level.setBlock(x, y, (byte) (3 + 9 * 16 + to));
|
||||
} else {
|
||||
// right pocket grass
|
||||
level.setBlock(x, y, (byte) (3 + 8 * 16 + to));
|
||||
}
|
||||
} else {
|
||||
if (b[0][0]) {
|
||||
level.setBlock(x, y, (byte) (2 + 10 * 16 + to));
|
||||
} else {
|
||||
level.setBlock(x, y, (byte) (0 + 10 * 16 + to));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
level.setBlock(x, y, (byte) (0 + 1 * 16 + to));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
216
src/dk/itu/mario/level/Level.java
Normal file
216
src/dk/itu/mario/level/Level.java
Normal file
@@ -0,0 +1,216 @@
|
||||
package dk.itu.mario.level;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import dk.itu.mario.MarioInterface.LevelInterface;
|
||||
import dk.itu.mario.engine.sprites.SpriteTemplate;
|
||||
|
||||
|
||||
public class Level implements LevelInterface
|
||||
{
|
||||
|
||||
protected static final byte BLOCK_EMPTY = (byte) (0 + 1 * 16);
|
||||
protected static final byte BLOCK_POWERUP = (byte) (4 + 2 + 1 * 16);
|
||||
protected static final byte BLOCK_COIN = (byte) (4 + 1 + 1 * 16);
|
||||
protected static final byte GROUND = (byte) (1 + 9 * 16);
|
||||
protected static final byte ROCK = (byte) (9 + 0 * 16);
|
||||
protected static final byte COIN = (byte) (2 + 2 * 16);
|
||||
|
||||
|
||||
protected static final byte LEFT_GRASS_EDGE = (byte) (0+9*16);
|
||||
protected static final byte RIGHT_GRASS_EDGE = (byte) (2+9*16);
|
||||
protected static final byte RIGHT_UP_GRASS_EDGE = (byte) (2+8*16);
|
||||
protected static final byte LEFT_UP_GRASS_EDGE = (byte) (0+8*16);
|
||||
protected static final byte LEFT_POCKET_GRASS = (byte) (3+9*16);
|
||||
protected static final byte RIGHT_POCKET_GRASS = (byte) (3+8*16);
|
||||
|
||||
protected static final byte HILL_FILL = (byte) (5 + 9 * 16);
|
||||
protected static final byte HILL_LEFT = (byte) (4 + 9 * 16);
|
||||
protected static final byte HILL_RIGHT = (byte) (6 + 9 * 16);
|
||||
protected static final byte HILL_TOP = (byte) (5 + 8 * 16);
|
||||
protected static final byte HILL_TOP_LEFT = (byte) (4 + 8 * 16);
|
||||
protected static final byte HILL_TOP_RIGHT = (byte) (6 + 8 * 16);
|
||||
|
||||
protected static final byte HILL_TOP_LEFT_IN = (byte) (4 + 11 * 16);
|
||||
protected static final byte HILL_TOP_RIGHT_IN = (byte) (6 + 11 * 16);
|
||||
|
||||
protected static final byte TUBE_TOP_LEFT = (byte) (10 + 0 * 16);
|
||||
protected static final byte TUBE_TOP_RIGHT = (byte) (11 + 0 * 16);
|
||||
|
||||
protected static final byte TUBE_SIDE_LEFT = (byte) (10 + 1 * 16);
|
||||
protected static final byte TUBE_SIDE_RIGHT = (byte) (11 + 1 * 16);
|
||||
|
||||
//The level's width and height
|
||||
protected int width;
|
||||
protected int height;
|
||||
|
||||
//This map of WIDTH * HEIGHT that contains the level's design
|
||||
private byte[][] map;
|
||||
|
||||
//This is a map of WIDTH * HEIGHT that contains the placement and type enemies
|
||||
private SpriteTemplate[][] spriteTemplates;
|
||||
|
||||
//These are the place of the end of the level
|
||||
protected int xExit;
|
||||
protected int yExit;
|
||||
|
||||
public Level(){
|
||||
|
||||
}
|
||||
|
||||
public Level(int width, int height)
|
||||
{
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
xExit = 10;
|
||||
yExit = 10;
|
||||
map = new byte[width][height];
|
||||
spriteTemplates = new SpriteTemplate[width][height];
|
||||
}
|
||||
|
||||
public static void loadBehaviors(DataInputStream dis) throws IOException
|
||||
{
|
||||
dis.readFully(Level.TILE_BEHAVIORS);
|
||||
}
|
||||
|
||||
public static void saveBehaviors(DataOutputStream dos) throws IOException
|
||||
{
|
||||
dos.write(Level.TILE_BEHAVIORS);
|
||||
}
|
||||
|
||||
/**
|
||||
*Clone the level data so that we can load it when Mario die
|
||||
*/
|
||||
public Level clone() throws CloneNotSupportedException {
|
||||
|
||||
Level clone=new Level(width, height);
|
||||
|
||||
clone.map = new byte[width][height];
|
||||
clone.spriteTemplates = new SpriteTemplate[width][height];
|
||||
clone.xExit = xExit;
|
||||
clone.yExit = yExit;
|
||||
|
||||
for (int i = 0; i < map.length; i++)
|
||||
for (int j = 0; j < map[i].length; j++) {
|
||||
clone.map[i][j]= map[i][j];
|
||||
clone.spriteTemplates[i][j] = spriteTemplates[i][j];
|
||||
}
|
||||
|
||||
return clone;
|
||||
|
||||
}
|
||||
|
||||
public void tick(){ }
|
||||
|
||||
public byte getBlockCapped(int x, int y)
|
||||
{
|
||||
if (x < 0) x = 0;
|
||||
if (y < 0) y = 0;
|
||||
if (x >= width) x = width - 1;
|
||||
if (y >= height) y = height - 1;
|
||||
return map[x][y];
|
||||
}
|
||||
|
||||
public byte getBlock(int x, int y)
|
||||
{
|
||||
if (x < 0) x = 0;
|
||||
if (y < 0) return 0;
|
||||
if (x >= width) x = width - 1;
|
||||
if (y >= height) y = height - 1;
|
||||
return map[x][y];
|
||||
}
|
||||
|
||||
public void setBlock(int x, int y, byte b)
|
||||
{
|
||||
if (x < 0) return;
|
||||
if (y < 0) return;
|
||||
if (x >= width) return;
|
||||
if (y >= height) return;
|
||||
map[x][y] = b;
|
||||
}
|
||||
|
||||
public boolean isBlocking(int x, int y, float xa, float ya)
|
||||
{
|
||||
byte block = getBlock(x, y);
|
||||
|
||||
boolean blocking = ((TILE_BEHAVIORS[block & 0xff]) & BIT_BLOCK_ALL) > 0;
|
||||
blocking |= (ya > 0) && ((TILE_BEHAVIORS[block & 0xff]) & BIT_BLOCK_UPPER) > 0;
|
||||
blocking |= (ya < 0) && ((TILE_BEHAVIORS[block & 0xff]) & BIT_BLOCK_LOWER) > 0;
|
||||
|
||||
return blocking;
|
||||
}
|
||||
|
||||
public SpriteTemplate getSpriteTemplate(int x, int y)
|
||||
{
|
||||
if (x < 0) return null;
|
||||
if (y < 0) return null;
|
||||
if (x >= width) return null;
|
||||
if (y >= height) return null;
|
||||
return spriteTemplates[x][y];
|
||||
}
|
||||
|
||||
public void setSpriteTemplate(int x, int y, SpriteTemplate spriteTemplate)
|
||||
{
|
||||
if (x < 0) return;
|
||||
if (y < 0) return;
|
||||
if (x >= width) return;
|
||||
if (y >= height) return;
|
||||
spriteTemplates[x][y] = spriteTemplate;
|
||||
}
|
||||
|
||||
public SpriteTemplate[][] getSpriteTemplate(){
|
||||
return this.spriteTemplates;
|
||||
}
|
||||
|
||||
public void resetSpriteTemplate(){
|
||||
for (int i = 0; i < spriteTemplates.length; i++) {
|
||||
for (int j = 0; j < spriteTemplates[i].length; j++) {
|
||||
|
||||
SpriteTemplate st = spriteTemplates[i][j];
|
||||
if(st != null)
|
||||
st.isDead = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void print(byte[][] array){
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
for (int j = 0; j < array[i].length; j++) {
|
||||
System.out.print(array[i][j]);
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
public byte[][] getMap() {
|
||||
return map;
|
||||
}
|
||||
public SpriteTemplate[][] getSpriteTemplates() {
|
||||
return spriteTemplates;
|
||||
}
|
||||
public int getxExit() {
|
||||
// TODO Auto-generated method stub
|
||||
return xExit;
|
||||
}
|
||||
public int getyExit() {
|
||||
// TODO Auto-generated method stub
|
||||
return yExit;
|
||||
}
|
||||
public int getWidth() {
|
||||
// TODO Auto-generated method stub
|
||||
return width;
|
||||
}
|
||||
public int getHeight() {
|
||||
// TODO Auto-generated method stub
|
||||
return height;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
// TODO Auto-generated method stub
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
130
src/dk/itu/mario/level/LevelEditView.java
Normal file
130
src/dk/itu/mario/level/LevelEditView.java
Normal file
@@ -0,0 +1,130 @@
|
||||
//package dk.itu.mario.level;
|
||||
//
|
||||
//import java.awt.Color;
|
||||
//import java.awt.Dimension;
|
||||
//import java.awt.Graphics;
|
||||
//import java.awt.event.MouseEvent;
|
||||
//import java.awt.event.MouseListener;
|
||||
//import java.awt.event.MouseMotionListener;
|
||||
//
|
||||
//import javax.swing.*;
|
||||
//import com.mojang.mario.*;
|
||||
//import com.mojang.mario.level.*;
|
||||
//
|
||||
//import dk.itu.mario.engine.Art;
|
||||
//import dk.itu.mario.engine.LevelRenderer;
|
||||
//
|
||||
//
|
||||
//
|
||||
//public class LevelEditView extends JComponent implements MouseListener, MouseMotionListener
|
||||
//{
|
||||
// private static final long serialVersionUID = -7696446733303717142L;
|
||||
//
|
||||
// private LevelRenderer levelRenderer;
|
||||
// private Level level;
|
||||
//
|
||||
// private int xTile = -1;
|
||||
// private int yTile = -1;
|
||||
// private TilePicker tilePicker;
|
||||
//
|
||||
// public LevelEditView(TilePicker tilePicker)
|
||||
// {
|
||||
// this.tilePicker = tilePicker;
|
||||
// level = new Level(256, 15);
|
||||
// Dimension size = new Dimension(level.width * 16, level.height * 16);
|
||||
// setPreferredSize(size);
|
||||
// setMinimumSize(size);
|
||||
// setMaximumSize(size);
|
||||
//
|
||||
// addMouseListener(this);
|
||||
// addMouseMotionListener(this);
|
||||
// }
|
||||
//
|
||||
// public void setLevel(Level level)
|
||||
// {
|
||||
// this.level = level;
|
||||
// Dimension size = new Dimension(level.width * 16, level.height * 16);
|
||||
// setPreferredSize(size);
|
||||
// setMinimumSize(size);
|
||||
// setMaximumSize(size);
|
||||
// repaint();
|
||||
// levelRenderer.setLevel(level);
|
||||
// }
|
||||
//
|
||||
// public Level getLevel()
|
||||
// {
|
||||
// return level;
|
||||
// }
|
||||
//
|
||||
// public void addNotify()
|
||||
// {
|
||||
// super.addNotify();
|
||||
// Art.init(getGraphicsConfiguration(), null);
|
||||
// levelRenderer = new LevelRenderer(level, getGraphicsConfiguration(), level.width * 16, level.height * 16);
|
||||
// levelRenderer.renderBehaviors = true;
|
||||
// }
|
||||
//
|
||||
// public void paintComponent(Graphics g)
|
||||
// {
|
||||
// g.setColor(new Color(0x8090ff));
|
||||
// g.fillRect(0, 0, level.width * 16, level.height * 16);
|
||||
// levelRenderer.render(g, 0, 0);
|
||||
// g.setColor(Color.BLACK);
|
||||
// g.drawRect(xTile * 16 - 1, yTile * 16 - 1, 17, 17);
|
||||
// }
|
||||
//
|
||||
// public void mouseClicked(MouseEvent e)
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// public void mouseEntered(MouseEvent e)
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// public void mouseExited(MouseEvent e)
|
||||
// {
|
||||
// xTile = -1;
|
||||
// yTile = -1;
|
||||
// repaint();
|
||||
// }
|
||||
//
|
||||
// public void mousePressed(MouseEvent e)
|
||||
// {
|
||||
// xTile = e.getX() / 16;
|
||||
// yTile = e.getY() / 16;
|
||||
//
|
||||
// if (e.getButton() == 3)
|
||||
// {
|
||||
// tilePicker.setPickedTile(level.getBlock(xTile, yTile));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// level.setBlock(xTile, yTile, tilePicker.pickedTile);
|
||||
// levelRenderer.repaint(xTile - 1, yTile - 1, 3, 3);
|
||||
//
|
||||
// repaint();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public void mouseReleased(MouseEvent e)
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// public void mouseDragged(MouseEvent e)
|
||||
// {
|
||||
// xTile = e.getX() / 16;
|
||||
// yTile = e.getY() / 16;
|
||||
//
|
||||
// level.setBlock(xTile, yTile, tilePicker.pickedTile);
|
||||
// levelRenderer.repaint(xTile - 1, yTile - 1, 3, 3);
|
||||
//
|
||||
// repaint();
|
||||
// }
|
||||
//
|
||||
// public void mouseMoved(MouseEvent e)
|
||||
// {
|
||||
// xTile = e.getX() / 16;
|
||||
// yTile = e.getY() / 16;
|
||||
// repaint();
|
||||
// }
|
||||
//}
|
||||
522
src/dk/itu/mario/level/MyLevel.java
Normal file
522
src/dk/itu/mario/level/MyLevel.java
Normal file
@@ -0,0 +1,522 @@
|
||||
package dk.itu.mario.level;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import dk.itu.mario.MarioInterface.GamePlay;
|
||||
import dk.itu.mario.MarioInterface.LevelInterface;
|
||||
import dk.itu.mario.engine.sprites.Enemy;
|
||||
import dk.itu.mario.engine.sprites.SpriteTemplate;
|
||||
|
||||
public class MyLevel extends Level {
|
||||
// Store information about the level
|
||||
public int ENEMIES = 0; // the number of enemies the level contains
|
||||
public int BLOCKS_EMPTY = 0; // the number of empty blocks
|
||||
public int BLOCKS_COINS = 0; // the number of coin blocks
|
||||
public int BLOCKS_POWER = 0; // the number of power blocks
|
||||
public int COINS = 0; // These are the coins in boxes that Mario collect
|
||||
|
||||
public static long lastSeed;
|
||||
|
||||
Random random;
|
||||
|
||||
private int difficulty;
|
||||
private int type;
|
||||
|
||||
public MyLevel(int width, int height) {
|
||||
super(width, height);
|
||||
}
|
||||
|
||||
public MyLevel(int width, int height, long seed, int difficulty, int type,
|
||||
GamePlay playerMetrics) {
|
||||
this(width, height);
|
||||
creat(seed, difficulty, type);
|
||||
}
|
||||
|
||||
public void creat(long seed, int difficulty, int type) {
|
||||
this.type = type;
|
||||
this.difficulty = difficulty;
|
||||
|
||||
lastSeed = seed;
|
||||
random = new Random(seed);
|
||||
|
||||
// create the start location
|
||||
int length = 0;
|
||||
length += buildStraight(0, width, true);
|
||||
|
||||
// create all of the medium sections
|
||||
while (length < width - 64) {
|
||||
length += buildStraight(length, width - length, false);
|
||||
length += buildStraight(length, width - length, false);
|
||||
length += buildHillStraight(length, width - length);
|
||||
length += buildJump(length, width - length);
|
||||
length += buildTubes(length, width - length);
|
||||
length += buildCannons(length, width - length);
|
||||
}
|
||||
|
||||
// set the end piece
|
||||
int floor = height - 1 - random.nextInt(4);
|
||||
|
||||
xExit = length + 8;
|
||||
yExit = floor;
|
||||
|
||||
// fills the end piece
|
||||
for (int x = length; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
if (y >= floor) {
|
||||
setBlock(x, y, GROUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type == LevelInterface.TYPE_CASTLE
|
||||
|| type == LevelInterface.TYPE_UNDERGROUND) {
|
||||
int ceiling = 0;
|
||||
int run = 0;
|
||||
for (int x = 0; x < width; x++) {
|
||||
if (run-- <= 0 && x > 4) {
|
||||
ceiling = random.nextInt(4);
|
||||
run = random.nextInt(4) + 4;
|
||||
}
|
||||
for (int y = 0; y < height; y++) {
|
||||
if ((x > 4 && y <= ceiling) || x < 1) {
|
||||
setBlock(x, y, GROUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fixWalls();
|
||||
|
||||
}
|
||||
|
||||
private int buildJump(int xo, int maxLength) {
|
||||
// jl: jump length
|
||||
// js: the number of blocks that are available at either side for free
|
||||
int js = random.nextInt(4) + 2;
|
||||
int jl = random.nextInt(2) + 2;
|
||||
int length = js * 2 + jl;
|
||||
|
||||
boolean hasStairs = random.nextInt(3) == 0;
|
||||
|
||||
int floor = height - 1 - random.nextInt(4);
|
||||
// run from the start x position, for the whole length
|
||||
for (int x = xo; x < xo + length; x++) {
|
||||
if (x < xo + js || x > xo + length - js - 1) {
|
||||
// run for all y's since we need to paint blocks upward
|
||||
for (int y = 0; y < height; y++) { // paint ground up until the
|
||||
// floor
|
||||
if (y >= floor) {
|
||||
setBlock(x, y, GROUND);
|
||||
}
|
||||
// if it is above ground, start making stairs of rocks
|
||||
else if (hasStairs) { // LEFT SIDE
|
||||
if (x < xo + js) { // we need to max it out and level
|
||||
// because it wont
|
||||
// paint ground correctly unless two
|
||||
// bricks are side by side
|
||||
if (y >= floor - (x - xo) + 1) {
|
||||
setBlock(x, y, ROCK);
|
||||
}
|
||||
} else { // RIGHT SIDE
|
||||
if (y >= floor - ((xo + length) - x) + 2) {
|
||||
setBlock(x, y, ROCK);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
private int buildCannons(int xo, int maxLength) {
|
||||
int length = random.nextInt(10) + 2;
|
||||
if (length > maxLength)
|
||||
length = maxLength;
|
||||
|
||||
int floor = height - 1 - random.nextInt(4);
|
||||
int xCannon = xo + 1 + random.nextInt(4);
|
||||
for (int x = xo; x < xo + length; x++) {
|
||||
if (x > xCannon) {
|
||||
xCannon += 2 + random.nextInt(4);
|
||||
}
|
||||
if (xCannon == xo + length - 1)
|
||||
xCannon += 10;
|
||||
int cannonHeight = floor - random.nextInt(4) - 1;
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
if (y >= floor) {
|
||||
setBlock(x, y, GROUND);
|
||||
} else {
|
||||
if (x == xCannon && y >= cannonHeight) {
|
||||
if (y == cannonHeight) {
|
||||
setBlock(x, y, (byte) (14 + 0 * 16));
|
||||
} else if (y == cannonHeight + 1) {
|
||||
setBlock(x, y, (byte) (14 + 1 * 16));
|
||||
} else {
|
||||
setBlock(x, y, (byte) (14 + 2 * 16));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
private int buildHillStraight(int xo, int maxLength) {
|
||||
int length = random.nextInt(10) + 10;
|
||||
if (length > maxLength)
|
||||
length = maxLength;
|
||||
|
||||
int floor = height - 1 - random.nextInt(4);
|
||||
for (int x = xo; x < xo + length; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
if (y >= floor) {
|
||||
setBlock(x, y, GROUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addEnemyLine(xo + 1, xo + length - 1, floor - 1);
|
||||
|
||||
int h = floor;
|
||||
|
||||
boolean keepGoing = true;
|
||||
|
||||
boolean[] occupied = new boolean[length];
|
||||
while (keepGoing) {
|
||||
h = h - 2 - random.nextInt(3);
|
||||
|
||||
if (h <= 0) {
|
||||
keepGoing = false;
|
||||
} else {
|
||||
int l = random.nextInt(5) + 3;
|
||||
int xxo = random.nextInt(length - l - 2) + xo + 1;
|
||||
|
||||
if (occupied[xxo - xo] || occupied[xxo - xo + l]
|
||||
|| occupied[xxo - xo - 1] || occupied[xxo - xo + l + 1]) {
|
||||
keepGoing = false;
|
||||
} else {
|
||||
occupied[xxo - xo] = true;
|
||||
occupied[xxo - xo + l] = true;
|
||||
addEnemyLine(xxo, xxo + l, h - 1);
|
||||
if (random.nextInt(4) == 0) {
|
||||
decorate(xxo - 1, xxo + l + 1, h);
|
||||
keepGoing = false;
|
||||
}
|
||||
for (int x = xxo; x < xxo + l; x++) {
|
||||
for (int y = h; y < floor; y++) {
|
||||
int xx = 5;
|
||||
if (x == xxo)
|
||||
xx = 4;
|
||||
if (x == xxo + l - 1)
|
||||
xx = 6;
|
||||
int yy = 9;
|
||||
if (y == h)
|
||||
yy = 8;
|
||||
|
||||
if (getBlock(x, y) == 0) {
|
||||
setBlock(x, y, (byte) (xx + yy * 16));
|
||||
} else {
|
||||
if (getBlock(x, y) == HILL_TOP_LEFT)
|
||||
setBlock(x, y, HILL_TOP_LEFT_IN);
|
||||
if (getBlock(x, y) == HILL_TOP_RIGHT)
|
||||
setBlock(x, y, HILL_TOP_RIGHT_IN);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
private void addEnemyLine(int x0, int x1, int y) {
|
||||
for (int x = x0; x < x1; x++) {
|
||||
if (random.nextInt(35) < difficulty + 1) {
|
||||
int type = random.nextInt(4);
|
||||
|
||||
if (difficulty < 1) {
|
||||
type = Enemy.ENEMY_GOOMBA;
|
||||
} else if (difficulty < 3) {
|
||||
type = random.nextInt(3);
|
||||
}
|
||||
|
||||
setSpriteTemplate(x, y,
|
||||
new SpriteTemplate(type,
|
||||
random.nextInt(35) < difficulty));
|
||||
ENEMIES++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int buildTubes(int xo, int maxLength) {
|
||||
int length = random.nextInt(10) + 5;
|
||||
if (length > maxLength)
|
||||
length = maxLength;
|
||||
|
||||
int floor = height - 1 - random.nextInt(4);
|
||||
int xTube = xo + 1 + random.nextInt(4);
|
||||
int tubeHeight = floor - random.nextInt(2) - 2;
|
||||
for (int x = xo; x < xo + length; x++) {
|
||||
if (x > xTube + 1) {
|
||||
xTube += 3 + random.nextInt(4);
|
||||
tubeHeight = floor - random.nextInt(2) - 2;
|
||||
}
|
||||
if (xTube >= xo + length - 2)
|
||||
xTube += 10;
|
||||
|
||||
if (x == xTube && random.nextInt(11) < difficulty + 1) {
|
||||
setSpriteTemplate(x, tubeHeight, new SpriteTemplate(
|
||||
Enemy.ENEMY_FLOWER, false));
|
||||
ENEMIES++;
|
||||
}
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
if (y >= floor) {
|
||||
setBlock(x, y, GROUND);
|
||||
|
||||
} else {
|
||||
if ((x == xTube || x == xTube + 1) && y >= tubeHeight) {
|
||||
int xPic = 10 + x - xTube;
|
||||
|
||||
if (y == tubeHeight) {
|
||||
// tube top
|
||||
setBlock(x, y, (byte) (xPic + 0 * 16));
|
||||
} else {
|
||||
// tube side
|
||||
setBlock(x, y, (byte) (xPic + 1 * 16));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
private int buildStraight(int xo, int maxLength, boolean safe) {
|
||||
int length = random.nextInt(10) + 2;
|
||||
|
||||
if (safe)
|
||||
length = 10 + random.nextInt(5);
|
||||
|
||||
if (length > maxLength)
|
||||
length = maxLength;
|
||||
|
||||
int floor = height - 1 - random.nextInt(4);
|
||||
|
||||
// runs from the specified x position to the length of the segment
|
||||
for (int x = xo; x < xo + length; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
if (y >= floor) {
|
||||
setBlock(x, y, GROUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!safe) {
|
||||
if (length > 5) {
|
||||
decorate(xo, xo + length, floor);
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
private void decorate(int xStart, int xLength, int floor) {
|
||||
// if its at the very top, just return
|
||||
if (floor < 1)
|
||||
return;
|
||||
|
||||
// boolean coins = random.nextInt(3) == 0;
|
||||
boolean rocks = true;
|
||||
|
||||
// add an enemy line above the box
|
||||
addEnemyLine(xStart + 1, xLength - 1, floor - 1);
|
||||
|
||||
int s = random.nextInt(4);
|
||||
int e = random.nextInt(4);
|
||||
|
||||
if (floor - 2 > 0) {
|
||||
if ((xLength - 1 - e) - (xStart + 1 + s) > 1) {
|
||||
for (int x = xStart + 1 + s; x < xLength - 1 - e; x++) {
|
||||
setBlock(x, floor - 2, COIN);
|
||||
COINS++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s = random.nextInt(4);
|
||||
e = random.nextInt(4);
|
||||
|
||||
// this fills the set of blocks and the hidden objects inside them
|
||||
if (floor - 4 > 0) {
|
||||
if ((xLength - 1 - e) - (xStart + 1 + s) > 2) {
|
||||
for (int x = xStart + 1 + s; x < xLength - 1 - e; x++) {
|
||||
if (rocks) {
|
||||
if (x != xStart + 1 && x != xLength - 2
|
||||
&& random.nextInt(3) == 0) {
|
||||
if (random.nextInt(4) == 0) {
|
||||
setBlock(x, floor - 4, BLOCK_POWERUP);
|
||||
BLOCKS_POWER++;
|
||||
} else { // the fills a block with a hidden coin
|
||||
setBlock(x, floor - 4, BLOCK_COIN);
|
||||
BLOCKS_COINS++;
|
||||
}
|
||||
} else if (random.nextInt(4) == 0) {
|
||||
if (random.nextInt(4) == 0) {
|
||||
setBlock(x, floor - 4, (byte) (2 + 1 * 16));
|
||||
} else {
|
||||
setBlock(x, floor - 4, (byte) (1 + 1 * 16));
|
||||
}
|
||||
} else {
|
||||
setBlock(x, floor - 4, BLOCK_EMPTY);
|
||||
BLOCKS_EMPTY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fixWalls() {
|
||||
boolean[][] blockMap = new boolean[width + 1][height + 1];
|
||||
|
||||
for (int x = 0; x < width + 1; x++) {
|
||||
for (int y = 0; y < height + 1; y++) {
|
||||
int blocks = 0;
|
||||
for (int xx = x - 1; xx < x + 1; xx++) {
|
||||
for (int yy = y - 1; yy < y + 1; yy++) {
|
||||
if (getBlockCapped(xx, yy) == GROUND) {
|
||||
blocks++;
|
||||
}
|
||||
}
|
||||
}
|
||||
blockMap[x][y] = blocks == 4;
|
||||
}
|
||||
}
|
||||
blockify(this, blockMap, width + 1, height + 1);
|
||||
}
|
||||
|
||||
private void blockify(Level level, boolean[][] blocks, int width, int height) {
|
||||
int to = 0;
|
||||
if (type == LevelInterface.TYPE_CASTLE) {
|
||||
to = 4 * 2;
|
||||
} else if (type == LevelInterface.TYPE_UNDERGROUND) {
|
||||
to = 4 * 3;
|
||||
}
|
||||
|
||||
boolean[][] b = new boolean[2][2];
|
||||
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int xx = x; xx <= x + 1; xx++) {
|
||||
for (int yy = y; yy <= y + 1; yy++) {
|
||||
int _xx = xx;
|
||||
int _yy = yy;
|
||||
if (_xx < 0)
|
||||
_xx = 0;
|
||||
if (_yy < 0)
|
||||
_yy = 0;
|
||||
if (_xx > width - 1)
|
||||
_xx = width - 1;
|
||||
if (_yy > height - 1)
|
||||
_yy = height - 1;
|
||||
b[xx - x][yy - y] = blocks[_xx][_yy];
|
||||
}
|
||||
}
|
||||
|
||||
if (b[0][0] == b[1][0] && b[0][1] == b[1][1]) {
|
||||
if (b[0][0] == b[0][1]) {
|
||||
if (b[0][0]) {
|
||||
level.setBlock(x, y, (byte) (1 + 9 * 16 + to));
|
||||
} else {
|
||||
// KEEP OLD BLOCK!
|
||||
}
|
||||
} else {
|
||||
if (b[0][0]) {
|
||||
// down grass top?
|
||||
level.setBlock(x, y, (byte) (1 + 10 * 16 + to));
|
||||
} else {
|
||||
// up grass top
|
||||
level.setBlock(x, y, (byte) (1 + 8 * 16 + to));
|
||||
}
|
||||
}
|
||||
} else if (b[0][0] == b[0][1] && b[1][0] == b[1][1]) {
|
||||
if (b[0][0]) {
|
||||
// right grass top
|
||||
level.setBlock(x, y, (byte) (2 + 9 * 16 + to));
|
||||
} else {
|
||||
// left grass top
|
||||
level.setBlock(x, y, (byte) (0 + 9 * 16 + to));
|
||||
}
|
||||
} else if (b[0][0] == b[1][1] && b[0][1] == b[1][0]) {
|
||||
level.setBlock(x, y, (byte) (1 + 9 * 16 + to));
|
||||
} else if (b[0][0] == b[1][0]) {
|
||||
if (b[0][0]) {
|
||||
if (b[0][1]) {
|
||||
level.setBlock(x, y, (byte) (3 + 10 * 16 + to));
|
||||
} else {
|
||||
level.setBlock(x, y, (byte) (3 + 11 * 16 + to));
|
||||
}
|
||||
} else {
|
||||
if (b[0][1]) {
|
||||
// right up grass top
|
||||
level.setBlock(x, y, (byte) (2 + 8 * 16 + to));
|
||||
} else {
|
||||
// left up grass top
|
||||
level.setBlock(x, y, (byte) (0 + 8 * 16 + to));
|
||||
}
|
||||
}
|
||||
} else if (b[0][1] == b[1][1]) {
|
||||
if (b[0][1]) {
|
||||
if (b[0][0]) {
|
||||
// left pocket grass
|
||||
level.setBlock(x, y, (byte) (3 + 9 * 16 + to));
|
||||
} else {
|
||||
// right pocket grass
|
||||
level.setBlock(x, y, (byte) (3 + 8 * 16 + to));
|
||||
}
|
||||
} else {
|
||||
if (b[0][0]) {
|
||||
level.setBlock(x, y, (byte) (2 + 10 * 16 + to));
|
||||
} else {
|
||||
level.setBlock(x, y, (byte) (0 + 10 * 16 + to));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
level.setBlock(x, y, (byte) (0 + 1 * 16 + to));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public RandomLevel clone() throws CloneNotSupportedException {
|
||||
|
||||
RandomLevel clone = new RandomLevel(width, height);
|
||||
|
||||
clone.xExit = xExit;
|
||||
clone.yExit = yExit;
|
||||
byte[][] map = getMap();
|
||||
SpriteTemplate[][] st = getSpriteTemplate();
|
||||
|
||||
for (int i = 0; i < map.length; i++)
|
||||
for (int j = 0; j < map[i].length; j++) {
|
||||
clone.setBlock(i, j, map[i][j]);
|
||||
clone.setSpriteTemplate(i, j, st[i][j]);
|
||||
}
|
||||
clone.BLOCKS_COINS = BLOCKS_COINS;
|
||||
clone.BLOCKS_EMPTY = BLOCKS_EMPTY;
|
||||
clone.BLOCKS_POWER = BLOCKS_POWER;
|
||||
clone.ENEMIES = ENEMIES;
|
||||
clone.COINS = COINS;
|
||||
|
||||
return clone;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
576
src/dk/itu/mario/level/RandomLevel.java
Normal file
576
src/dk/itu/mario/level/RandomLevel.java
Normal file
@@ -0,0 +1,576 @@
|
||||
package dk.itu.mario.level;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import dk.itu.mario.MarioInterface.Constraints;
|
||||
import dk.itu.mario.MarioInterface.LevelInterface;
|
||||
import dk.itu.mario.engine.sprites.SpriteTemplate;
|
||||
import dk.itu.mario.engine.sprites.Enemy;
|
||||
|
||||
public class RandomLevel extends Level {
|
||||
// Store information about the level
|
||||
public int ENEMIES = 0; // the number of enemies the level contains
|
||||
public int BLOCKS_EMPTY = 0; // the number of empty blocks
|
||||
public int BLOCKS_COINS = 0; // the number of coin blocks
|
||||
public int BLOCKS_POWER = 0; // the number of power blocks
|
||||
public int COINS = 0; // These are the coins in boxes that Mario collect
|
||||
|
||||
public static long lastSeed;
|
||||
|
||||
Random random;
|
||||
|
||||
private static final int ODDS_STRAIGHT = 0;
|
||||
private static final int ODDS_HILL_STRAIGHT = 1;
|
||||
private static final int ODDS_TUBES = 2;
|
||||
private static final int ODDS_JUMP = 3;
|
||||
private static final int ODDS_CANNONS = 4;
|
||||
|
||||
private int[] odds = new int[5];
|
||||
|
||||
private int totalOdds;
|
||||
|
||||
private int difficulty;
|
||||
private int type;
|
||||
private int gaps;
|
||||
|
||||
public RandomLevel(int width, int height) {
|
||||
super(width, height);
|
||||
}
|
||||
|
||||
public RandomLevel(int width, int height, long seed, int difficulty,
|
||||
int type) {
|
||||
this(width, height);
|
||||
creat(seed, difficulty, type);
|
||||
}
|
||||
|
||||
public void creat(long seed, int difficulty, int type) {
|
||||
this.type = type;
|
||||
this.difficulty = difficulty;
|
||||
odds[ODDS_STRAIGHT] = 20;
|
||||
odds[ODDS_HILL_STRAIGHT] = 10;
|
||||
odds[ODDS_TUBES] = 2 + 1 * difficulty;
|
||||
odds[ODDS_JUMP] = 2 * difficulty;
|
||||
odds[ODDS_CANNONS] = -10 + 5 * difficulty;
|
||||
|
||||
if (type != LevelInterface.TYPE_OVERGROUND) {
|
||||
odds[ODDS_HILL_STRAIGHT] = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < odds.length; i++) {
|
||||
// failsafe (no negative odds)
|
||||
if (odds[i] < 0) {
|
||||
odds[i] = 0;
|
||||
}
|
||||
|
||||
totalOdds += odds[i];
|
||||
odds[i] = totalOdds - odds[i];
|
||||
}
|
||||
|
||||
lastSeed = seed;
|
||||
random = new Random(seed);
|
||||
|
||||
// create the start location
|
||||
int length = 0;
|
||||
length += buildStraight(0, width, true);
|
||||
|
||||
// create all of the medium sections
|
||||
while (length < width - 64) {
|
||||
length += buildZone(length, width - length);
|
||||
}
|
||||
|
||||
// set the end piece
|
||||
int floor = height - 1 - random.nextInt(4);
|
||||
|
||||
xExit = length + 8;
|
||||
yExit = floor;
|
||||
|
||||
// fills the end piece
|
||||
for (int x = length; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
if (y >= floor) {
|
||||
setBlock(x, y, GROUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type == LevelInterface.TYPE_CASTLE
|
||||
|| type == LevelInterface.TYPE_UNDERGROUND) {
|
||||
int ceiling = 0;
|
||||
int run = 0;
|
||||
for (int x = 0; x < width; x++) {
|
||||
if (run-- <= 0 && x > 4) {
|
||||
ceiling = random.nextInt(4);
|
||||
run = random.nextInt(4) + 4;
|
||||
}
|
||||
for (int y = 0; y < height; y++) {
|
||||
if ((x > 4 && y <= ceiling) || x < 1) {
|
||||
setBlock(x, y, GROUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fixWalls();
|
||||
|
||||
}
|
||||
|
||||
private int buildZone(int x, int maxLength) {
|
||||
int t = random.nextInt(totalOdds);
|
||||
int type = 0;
|
||||
|
||||
for (int i = 0; i < odds.length; i++) {
|
||||
if (odds[i] <= t) {
|
||||
type = i;
|
||||
}
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case ODDS_STRAIGHT:
|
||||
return buildStraight(x, maxLength, false);
|
||||
case ODDS_HILL_STRAIGHT:
|
||||
return buildHillStraight(x, maxLength);
|
||||
case ODDS_TUBES:
|
||||
return buildTubes(x, maxLength);
|
||||
case ODDS_JUMP:
|
||||
if (gaps < Constraints.gaps)
|
||||
return buildJump(x, maxLength);
|
||||
else
|
||||
return buildStraight(x, maxLength, false);
|
||||
case ODDS_CANNONS:
|
||||
return buildCannons(x, maxLength);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int buildJump(int xo, int maxLength) {
|
||||
gaps++;
|
||||
// jl: jump length
|
||||
// js: the number of blocks that are available at either side for free
|
||||
int js = random.nextInt(4) + 2;
|
||||
int jl = random.nextInt(2) + 2;
|
||||
int length = js * 2 + jl;
|
||||
|
||||
boolean hasStairs = random.nextInt(3) == 0;
|
||||
|
||||
int floor = height - 1 - random.nextInt(4);
|
||||
// run from the start x position, for the whole length
|
||||
for (int x = xo; x < xo + length; x++) {
|
||||
if (x < xo + js || x > xo + length - js - 1) {
|
||||
// run for all y's since we need to paint blocks upward
|
||||
for (int y = 0; y < height; y++) { // paint ground up until the
|
||||
// floor
|
||||
if (y >= floor) {
|
||||
setBlock(x, y, GROUND);
|
||||
}
|
||||
// if it is above ground, start making stairs of rocks
|
||||
else if (hasStairs) { // LEFT SIDE
|
||||
if (x < xo + js) { // we need to max it out and level
|
||||
// because it wont
|
||||
// paint ground correctly unless two
|
||||
// bricks are side by side
|
||||
if (y >= floor - (x - xo) + 1) {
|
||||
setBlock(x, y, ROCK);
|
||||
}
|
||||
} else { // RIGHT SIDE
|
||||
if (y >= floor - ((xo + length) - x) + 2) {
|
||||
setBlock(x, y, ROCK);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
private int buildCannons(int xo, int maxLength) {
|
||||
int length = random.nextInt(10) + 2;
|
||||
if (length > maxLength)
|
||||
length = maxLength;
|
||||
|
||||
int floor = height - 1 - random.nextInt(4);
|
||||
int xCannon = xo + 1 + random.nextInt(4);
|
||||
for (int x = xo; x < xo + length; x++) {
|
||||
if (x > xCannon) {
|
||||
xCannon += 2 + random.nextInt(4);
|
||||
}
|
||||
if (xCannon == xo + length - 1)
|
||||
xCannon += 10;
|
||||
int cannonHeight = floor - random.nextInt(4) - 1;
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
if (y >= floor) {
|
||||
setBlock(x, y, GROUND);
|
||||
} else {
|
||||
if (x == xCannon && y >= cannonHeight) {
|
||||
if (y == cannonHeight) {
|
||||
setBlock(x, y, (byte) (14 + 0 * 16));
|
||||
} else if (y == cannonHeight + 1) {
|
||||
setBlock(x, y, (byte) (14 + 1 * 16));
|
||||
} else {
|
||||
setBlock(x, y, (byte) (14 + 2 * 16));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
private int buildHillStraight(int xo, int maxLength) {
|
||||
int length = random.nextInt(10) + 10;
|
||||
if (length > maxLength)
|
||||
length = maxLength;
|
||||
|
||||
int floor = height - 1 - random.nextInt(4);
|
||||
for (int x = xo; x < xo + length; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
if (y >= floor) {
|
||||
setBlock(x, y, GROUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addEnemyLine(xo + 1, xo + length - 1, floor - 1);
|
||||
|
||||
int h = floor;
|
||||
|
||||
boolean keepGoing = true;
|
||||
|
||||
boolean[] occupied = new boolean[length];
|
||||
while (keepGoing) {
|
||||
h = h - 2 - random.nextInt(3);
|
||||
|
||||
if (h <= 0) {
|
||||
keepGoing = false;
|
||||
} else {
|
||||
int l = random.nextInt(5) + 3;
|
||||
int xxo = random.nextInt(length - l - 2) + xo + 1;
|
||||
|
||||
if (occupied[xxo - xo] || occupied[xxo - xo + l]
|
||||
|| occupied[xxo - xo - 1] || occupied[xxo - xo + l + 1]) {
|
||||
keepGoing = false;
|
||||
} else {
|
||||
occupied[xxo - xo] = true;
|
||||
occupied[xxo - xo + l] = true;
|
||||
addEnemyLine(xxo, xxo + l, h - 1);
|
||||
if (random.nextInt(4) == 0) {
|
||||
decorate(xxo - 1, xxo + l + 1, h);
|
||||
keepGoing = false;
|
||||
}
|
||||
for (int x = xxo; x < xxo + l; x++) {
|
||||
for (int y = h; y < floor; y++) {
|
||||
int xx = 5;
|
||||
if (x == xxo)
|
||||
xx = 4;
|
||||
if (x == xxo + l - 1)
|
||||
xx = 6;
|
||||
int yy = 9;
|
||||
if (y == h)
|
||||
yy = 8;
|
||||
|
||||
if (getBlock(x, y) == 0) {
|
||||
setBlock(x, y, (byte) (xx + yy * 16));
|
||||
} else {
|
||||
if (getBlock(x, y) == HILL_TOP_LEFT)
|
||||
setBlock(x, y, HILL_TOP_LEFT_IN);
|
||||
if (getBlock(x, y) == HILL_TOP_RIGHT)
|
||||
setBlock(x, y, HILL_TOP_RIGHT_IN);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
private void addEnemyLine(int x0, int x1, int y) {
|
||||
for (int x = x0; x < x1; x++) {
|
||||
if (random.nextInt(35) < difficulty + 1) {
|
||||
int type = random.nextInt(4);
|
||||
|
||||
if (difficulty < 1) {
|
||||
type = Enemy.ENEMY_GOOMBA;
|
||||
} else if (difficulty < 3) {
|
||||
type = random.nextInt(3);
|
||||
}
|
||||
|
||||
setSpriteTemplate(x, y,
|
||||
new SpriteTemplate(type,
|
||||
random.nextInt(35) < difficulty));
|
||||
ENEMIES++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int buildTubes(int xo, int maxLength) {
|
||||
int length = random.nextInt(10) + 5;
|
||||
if (length > maxLength)
|
||||
length = maxLength;
|
||||
|
||||
int floor = height - 1 - random.nextInt(4);
|
||||
int xTube = xo + 1 + random.nextInt(4);
|
||||
int tubeHeight = floor - random.nextInt(2) - 2;
|
||||
for (int x = xo; x < xo + length; x++) {
|
||||
if (x > xTube + 1) {
|
||||
xTube += 3 + random.nextInt(4);
|
||||
tubeHeight = floor - random.nextInt(2) - 2;
|
||||
}
|
||||
if (xTube >= xo + length - 2)
|
||||
xTube += 10;
|
||||
|
||||
if (x == xTube && random.nextInt(11) < difficulty + 1) {
|
||||
setSpriteTemplate(x, tubeHeight, new SpriteTemplate(
|
||||
Enemy.ENEMY_FLOWER, false));
|
||||
ENEMIES++;
|
||||
}
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
if (y >= floor) {
|
||||
setBlock(x, y, GROUND);
|
||||
|
||||
} else {
|
||||
if ((x == xTube || x == xTube + 1) && y >= tubeHeight) {
|
||||
int xPic = 10 + x - xTube;
|
||||
|
||||
if (y == tubeHeight) {
|
||||
// tube top
|
||||
setBlock(x, y, (byte) (xPic + 0 * 16));
|
||||
} else {
|
||||
// tube side
|
||||
setBlock(x, y, (byte) (xPic + 1 * 16));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
private int buildStraight(int xo, int maxLength, boolean safe) {
|
||||
int length = random.nextInt(10) + 2;
|
||||
|
||||
if (safe)
|
||||
length = 10 + random.nextInt(5);
|
||||
|
||||
if (length > maxLength)
|
||||
length = maxLength;
|
||||
|
||||
int floor = height - 1 - random.nextInt(4);
|
||||
|
||||
// runs from the specified x position to the length of the segment
|
||||
for (int x = xo; x < xo + length; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
if (y >= floor) {
|
||||
setBlock(x, y, GROUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!safe) {
|
||||
if (length > 5) {
|
||||
decorate(xo, xo + length, floor);
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
private void decorate(int xStart, int xLength, int floor) {
|
||||
// if its at the very top, just return
|
||||
if (floor < 1)
|
||||
return;
|
||||
|
||||
// boolean coins = random.nextInt(3) == 0;
|
||||
boolean rocks = true;
|
||||
|
||||
// add an enemy line above the box
|
||||
addEnemyLine(xStart + 1, xLength - 1, floor - 1);
|
||||
|
||||
int s = random.nextInt(4);
|
||||
int e = random.nextInt(4);
|
||||
|
||||
if (floor - 2 > 0) {
|
||||
if ((xLength - 1 - e) - (xStart + 1 + s) > 1) {
|
||||
for (int x = xStart + 1 + s; x < xLength - 1 - e; x++) {
|
||||
setBlock(x, floor - 2, COIN);
|
||||
COINS++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s = random.nextInt(4);
|
||||
e = random.nextInt(4);
|
||||
|
||||
// this fills the set of blocks and the hidden objects inside them
|
||||
if (floor - 4 > 0) {
|
||||
if ((xLength - 1 - e) - (xStart + 1 + s) > 2) {
|
||||
for (int x = xStart + 1 + s; x < xLength - 1 - e; x++) {
|
||||
if (rocks) {
|
||||
if (x != xStart + 1 && x != xLength - 2
|
||||
&& random.nextInt(3) == 0) {
|
||||
if (random.nextInt(4) == 0) {
|
||||
setBlock(x, floor - 4, BLOCK_POWERUP);
|
||||
BLOCKS_POWER++;
|
||||
} else { // the fills a block with a hidden coin
|
||||
setBlock(x, floor - 4, BLOCK_COIN);
|
||||
BLOCKS_COINS++;
|
||||
}
|
||||
} else if (random.nextInt(4) == 0) {
|
||||
if (random.nextInt(4) == 0) {
|
||||
setBlock(x, floor - 4, (byte) (2 + 1 * 16));
|
||||
} else {
|
||||
setBlock(x, floor - 4, (byte) (1 + 1 * 16));
|
||||
}
|
||||
} else {
|
||||
setBlock(x, floor - 4, BLOCK_EMPTY);
|
||||
BLOCKS_EMPTY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fixWalls() {
|
||||
boolean[][] blockMap = new boolean[width + 1][height + 1];
|
||||
|
||||
for (int x = 0; x < width + 1; x++) {
|
||||
for (int y = 0; y < height + 1; y++) {
|
||||
int blocks = 0;
|
||||
for (int xx = x - 1; xx < x + 1; xx++) {
|
||||
for (int yy = y - 1; yy < y + 1; yy++) {
|
||||
if (getBlockCapped(xx, yy) == GROUND) {
|
||||
blocks++;
|
||||
}
|
||||
}
|
||||
}
|
||||
blockMap[x][y] = blocks == 4;
|
||||
}
|
||||
}
|
||||
blockify(this, blockMap, width + 1, height + 1);
|
||||
}
|
||||
|
||||
private void blockify(Level level, boolean[][] blocks, int width, int height) {
|
||||
int to = 0;
|
||||
if (type == LevelInterface.TYPE_CASTLE) {
|
||||
to = 4 * 2;
|
||||
} else if (type == LevelInterface.TYPE_UNDERGROUND) {
|
||||
to = 4 * 3;
|
||||
}
|
||||
|
||||
boolean[][] b = new boolean[2][2];
|
||||
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int xx = x; xx <= x + 1; xx++) {
|
||||
for (int yy = y; yy <= y + 1; yy++) {
|
||||
int _xx = xx;
|
||||
int _yy = yy;
|
||||
if (_xx < 0)
|
||||
_xx = 0;
|
||||
if (_yy < 0)
|
||||
_yy = 0;
|
||||
if (_xx > width - 1)
|
||||
_xx = width - 1;
|
||||
if (_yy > height - 1)
|
||||
_yy = height - 1;
|
||||
b[xx - x][yy - y] = blocks[_xx][_yy];
|
||||
}
|
||||
}
|
||||
|
||||
if (b[0][0] == b[1][0] && b[0][1] == b[1][1]) {
|
||||
if (b[0][0] == b[0][1]) {
|
||||
if (b[0][0]) {
|
||||
level.setBlock(x, y, (byte) (1 + 9 * 16 + to));
|
||||
} else {
|
||||
// KEEP OLD BLOCK!
|
||||
}
|
||||
} else {
|
||||
if (b[0][0]) {
|
||||
// down grass top?
|
||||
level.setBlock(x, y, (byte) (1 + 10 * 16 + to));
|
||||
} else {
|
||||
// up grass top
|
||||
level.setBlock(x, y, (byte) (1 + 8 * 16 + to));
|
||||
}
|
||||
}
|
||||
} else if (b[0][0] == b[0][1] && b[1][0] == b[1][1]) {
|
||||
if (b[0][0]) {
|
||||
// right grass top
|
||||
level.setBlock(x, y, (byte) (2 + 9 * 16 + to));
|
||||
} else {
|
||||
// left grass top
|
||||
level.setBlock(x, y, (byte) (0 + 9 * 16 + to));
|
||||
}
|
||||
} else if (b[0][0] == b[1][1] && b[0][1] == b[1][0]) {
|
||||
level.setBlock(x, y, (byte) (1 + 9 * 16 + to));
|
||||
} else if (b[0][0] == b[1][0]) {
|
||||
if (b[0][0]) {
|
||||
if (b[0][1]) {
|
||||
level.setBlock(x, y, (byte) (3 + 10 * 16 + to));
|
||||
} else {
|
||||
level.setBlock(x, y, (byte) (3 + 11 * 16 + to));
|
||||
}
|
||||
} else {
|
||||
if (b[0][1]) {
|
||||
// right up grass top
|
||||
level.setBlock(x, y, (byte) (2 + 8 * 16 + to));
|
||||
} else {
|
||||
// left up grass top
|
||||
level.setBlock(x, y, (byte) (0 + 8 * 16 + to));
|
||||
}
|
||||
}
|
||||
} else if (b[0][1] == b[1][1]) {
|
||||
if (b[0][1]) {
|
||||
if (b[0][0]) {
|
||||
// left pocket grass
|
||||
level.setBlock(x, y, (byte) (3 + 9 * 16 + to));
|
||||
} else {
|
||||
// right pocket grass
|
||||
level.setBlock(x, y, (byte) (3 + 8 * 16 + to));
|
||||
}
|
||||
} else {
|
||||
if (b[0][0]) {
|
||||
level.setBlock(x, y, (byte) (2 + 10 * 16 + to));
|
||||
} else {
|
||||
level.setBlock(x, y, (byte) (0 + 10 * 16 + to));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
level.setBlock(x, y, (byte) (0 + 1 * 16 + to));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public RandomLevel clone() throws CloneNotSupportedException {
|
||||
|
||||
RandomLevel clone = new RandomLevel(width, height);
|
||||
|
||||
clone.xExit = xExit;
|
||||
clone.yExit = yExit;
|
||||
byte[][] map = getMap();
|
||||
SpriteTemplate[][] st = getSpriteTemplate();
|
||||
|
||||
for (int i = 0; i < map.length; i++)
|
||||
for (int j = 0; j < map[i].length; j++) {
|
||||
clone.setBlock(i, j, map[i][j]);
|
||||
clone.setSpriteTemplate(i, j, st[i][j]);
|
||||
}
|
||||
clone.BLOCKS_COINS = BLOCKS_COINS;
|
||||
clone.BLOCKS_EMPTY = BLOCKS_EMPTY;
|
||||
clone.BLOCKS_POWER = BLOCKS_POWER;
|
||||
clone.ENEMIES = ENEMIES;
|
||||
clone.COINS = COINS;
|
||||
|
||||
return clone;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
BIN
src/dk/itu/mario/level/generator/.DS_Store
vendored
Normal file
BIN
src/dk/itu/mario/level/generator/.DS_Store
vendored
Normal file
Binary file not shown.
@@ -0,0 +1,25 @@
|
||||
package dk.itu.mario.level.generator;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import dk.itu.mario.MarioInterface.GamePlay;
|
||||
import dk.itu.mario.MarioInterface.LevelGenerator;
|
||||
import dk.itu.mario.MarioInterface.LevelInterface;
|
||||
import dk.itu.mario.level.CustomizedLevel;
|
||||
|
||||
public class CustomizedLevelGenerator implements LevelGenerator {
|
||||
|
||||
public LevelInterface generateLevel(GamePlay playerMetrics) {
|
||||
System.out.println("Generating customized level");
|
||||
LevelInterface level = new CustomizedLevel(320, 15,
|
||||
new Random().nextLong(), 1, 1, playerMetrics);
|
||||
return level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LevelInterface generateLevel(String detailedInfo) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
26
src/dk/itu/mario/level/generator/MyLevelGenerator.java
Normal file
26
src/dk/itu/mario/level/generator/MyLevelGenerator.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package dk.itu.mario.level.generator;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import dk.itu.mario.MarioInterface.GamePlay;
|
||||
import dk.itu.mario.MarioInterface.LevelGenerator;
|
||||
import dk.itu.mario.MarioInterface.LevelInterface;
|
||||
import dk.itu.mario.level.MyLevel;
|
||||
|
||||
public class MyLevelGenerator extends CustomizedLevelGenerator implements
|
||||
LevelGenerator {
|
||||
|
||||
public LevelInterface generateLevel(GamePlay playerMetrics) {
|
||||
System.out.println("Generating my level");
|
||||
LevelInterface level = new MyLevel(320, 15, new Random().nextLong(), 1,
|
||||
LevelInterface.TYPE_OVERGROUND, playerMetrics);
|
||||
return level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LevelInterface generateLevel(String detailedInfo) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
26
src/dk/itu/mario/level/generator/RandomLevelGenerator.java
Normal file
26
src/dk/itu/mario/level/generator/RandomLevelGenerator.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package dk.itu.mario.level.generator;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import dk.itu.mario.MarioInterface.GamePlay;
|
||||
import dk.itu.mario.MarioInterface.LevelGenerator;
|
||||
import dk.itu.mario.MarioInterface.LevelInterface;
|
||||
import dk.itu.mario.level.RandomLevel;
|
||||
|
||||
public class RandomLevelGenerator extends CustomizedLevelGenerator implements
|
||||
LevelGenerator {
|
||||
|
||||
public LevelInterface generateLevel(GamePlay playerMetrics) {
|
||||
System.out.println("Generating random level");
|
||||
LevelInterface level = new RandomLevel(320, 15,
|
||||
new Random().nextLong(), 1, LevelInterface.TYPE_OVERGROUND);
|
||||
return level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LevelInterface generateLevel(String detailedInfo) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
BIN
src/dk/itu/mario/scene/.DS_Store
vendored
Normal file
BIN
src/dk/itu/mario/scene/.DS_Store
vendored
Normal file
Binary file not shown.
601
src/dk/itu/mario/scene/LevelScene.java
Normal file
601
src/dk/itu/mario/scene/LevelScene.java
Normal file
@@ -0,0 +1,601 @@
|
||||
package dk.itu.mario.scene;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Image;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import dk.itu.mario.engine.Art;
|
||||
import dk.itu.mario.engine.BgRenderer;
|
||||
import dk.itu.mario.engine.DataRecorder;
|
||||
import dk.itu.mario.engine.LevelRenderer;
|
||||
import dk.itu.mario.engine.MarioComponent;
|
||||
import dk.itu.mario.engine.sonar.FixedSoundSource;
|
||||
import dk.itu.mario.engine.sprites.BulletBill;
|
||||
import dk.itu.mario.engine.sprites.CoinAnim;
|
||||
import dk.itu.mario.engine.sprites.FireFlower;
|
||||
import dk.itu.mario.engine.sprites.Fireball;
|
||||
import dk.itu.mario.engine.sprites.Mario;
|
||||
import dk.itu.mario.engine.sprites.Mushroom;
|
||||
import dk.itu.mario.engine.sprites.Particle;
|
||||
import dk.itu.mario.engine.sprites.Shell;
|
||||
import dk.itu.mario.engine.sprites.Sparkle;
|
||||
import dk.itu.mario.engine.sprites.Sprite;
|
||||
import dk.itu.mario.engine.sprites.SpriteContext;
|
||||
import dk.itu.mario.engine.sprites.SpriteTemplate;
|
||||
import dk.itu.mario.level.Level;
|
||||
|
||||
public class LevelScene extends Scene implements SpriteContext {
|
||||
protected List<Sprite> sprites = new ArrayList<Sprite>();
|
||||
protected List<Sprite> spritesToAdd = new ArrayList<Sprite>();
|
||||
protected List<Sprite> spritesToRemove = new ArrayList<Sprite>();
|
||||
|
||||
public Level level;
|
||||
public Mario mario;
|
||||
public float xCam, yCam, xCamO, yCamO;
|
||||
public static Image tmpImage;
|
||||
protected int tick;
|
||||
|
||||
protected LevelRenderer layer;
|
||||
protected BgRenderer[] bgLayer = new BgRenderer[2];
|
||||
protected Level currentLevel;
|
||||
protected GraphicsConfiguration graphicsConfiguration;
|
||||
|
||||
public boolean paused = false;
|
||||
public int startTime = 0;
|
||||
public int timeLeft;
|
||||
|
||||
protected long levelSeed;
|
||||
protected MarioComponent marioComponent;
|
||||
protected int levelType;
|
||||
protected int levelDifficulty;
|
||||
|
||||
public static DataRecorder recorder;
|
||||
|
||||
public boolean gameStarted;
|
||||
|
||||
public static boolean bothPlayed = false;
|
||||
|
||||
private int[] xPositionsArrow;
|
||||
private int[] yPositionsArrow;
|
||||
private int widthArrow, heightArrow, tipWidthArrow;
|
||||
private int xArrow, yArrow;
|
||||
|
||||
public LevelScene(GraphicsConfiguration graphicsConfiguration,
|
||||
MarioComponent renderer, long seed, int levelDifficulty, int type) {
|
||||
this.graphicsConfiguration = graphicsConfiguration;
|
||||
this.levelSeed = seed;
|
||||
this.marioComponent = renderer;
|
||||
this.levelDifficulty = levelDifficulty;
|
||||
this.levelType = type;
|
||||
|
||||
widthArrow = 25;
|
||||
tipWidthArrow = 10;
|
||||
heightArrow = 20;
|
||||
|
||||
xArrow = 160;
|
||||
yArrow = 40;
|
||||
|
||||
xPositionsArrow = new int[] { xArrow + -widthArrow / 2,
|
||||
xArrow + widthArrow / 2 - tipWidthArrow,
|
||||
xArrow + widthArrow / 2 - tipWidthArrow,
|
||||
xArrow + widthArrow / 2,
|
||||
xArrow + widthArrow / 2 - tipWidthArrow,
|
||||
xArrow + widthArrow / 2 - tipWidthArrow,
|
||||
xArrow + -widthArrow / 2 };
|
||||
yPositionsArrow = new int[] { yArrow + -heightArrow / 4,
|
||||
yArrow + -heightArrow / 4, yArrow + -heightArrow / 2,
|
||||
yArrow + 0, yArrow + heightArrow / 2, yArrow + heightArrow / 4,
|
||||
yArrow + heightArrow / 4 };
|
||||
}
|
||||
|
||||
public void init() {
|
||||
|
||||
}
|
||||
|
||||
public int fireballsOnScreen = 0;
|
||||
|
||||
List<Shell> shellsToCheck = new ArrayList<Shell>();
|
||||
|
||||
public void checkShellCollide(Shell shell) {
|
||||
shellsToCheck.add(shell);
|
||||
}
|
||||
|
||||
List<Fireball> fireballsToCheck = new ArrayList<Fireball>();
|
||||
|
||||
public void checkFireballCollide(Fireball fireball) {
|
||||
fireballsToCheck.add(fireball);
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
timeLeft--;
|
||||
|
||||
if (widthArrow < 0) {
|
||||
widthArrow *= -1;
|
||||
tipWidthArrow *= -1;
|
||||
|
||||
xPositionsArrow = new int[] { xArrow + -widthArrow / 2,
|
||||
xArrow + widthArrow / 2 - tipWidthArrow,
|
||||
xArrow + widthArrow / 2 - tipWidthArrow,
|
||||
xArrow + widthArrow / 2,
|
||||
xArrow + widthArrow / 2 - tipWidthArrow,
|
||||
xArrow + widthArrow / 2 - tipWidthArrow,
|
||||
xArrow + -widthArrow / 2 };
|
||||
yPositionsArrow = new int[] { yArrow + -heightArrow / 4,
|
||||
yArrow + -heightArrow / 4, yArrow + -heightArrow / 2,
|
||||
yArrow + 0, yArrow + heightArrow / 2,
|
||||
yArrow + heightArrow / 4, yArrow + heightArrow / 4 };
|
||||
|
||||
}
|
||||
|
||||
if (timeLeft == 0) {
|
||||
mario.dieTime();
|
||||
}
|
||||
|
||||
xCamO = xCam;
|
||||
yCamO = yCam;
|
||||
|
||||
if (startTime > 0) {
|
||||
startTime++;
|
||||
}
|
||||
|
||||
float targetXCam = mario.x - 160;
|
||||
|
||||
xCam = targetXCam;
|
||||
|
||||
if (xCam < 0)
|
||||
xCam = 0;
|
||||
if (xCam > level.getWidth() * 16 - 320)
|
||||
xCam = level.getWidth() * 16 - 320;
|
||||
|
||||
/*
|
||||
* if (recorder != null) { recorder.addTick(mario.getKeyMask()); }
|
||||
*
|
||||
* if (replayer!=null) { mario.setKeys(replayer.nextTick()); }
|
||||
*/
|
||||
|
||||
fireballsOnScreen = 0;
|
||||
|
||||
for (Sprite sprite : sprites) {
|
||||
if (sprite != mario) {
|
||||
float xd = sprite.x - xCam;
|
||||
float yd = sprite.y - yCam;
|
||||
if (xd < -64 || xd > 320 + 64 || yd < -64 || yd > 240 + 64) {
|
||||
removeSprite(sprite);
|
||||
} else {
|
||||
if (sprite instanceof Fireball) {
|
||||
fireballsOnScreen++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (paused) {
|
||||
for (Sprite sprite : sprites) {
|
||||
if (sprite == mario) {
|
||||
sprite.tick();
|
||||
} else {
|
||||
sprite.tickNoMove();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
tick++;
|
||||
level.tick();
|
||||
|
||||
boolean hasShotCannon = false;
|
||||
int xCannon = 0;
|
||||
|
||||
for (int x = (int) xCam / 16 - 1; x <= (int) (xCam + layer.width) / 16 + 1; x++)
|
||||
for (int y = (int) yCam / 16 - 1; y <= (int) (yCam + layer.height) / 16 + 1; y++) {
|
||||
int dir = 0;
|
||||
|
||||
if (x * 16 + 8 > mario.x + 16)
|
||||
dir = -1;
|
||||
if (x * 16 + 8 < mario.x - 16)
|
||||
dir = 1;
|
||||
|
||||
SpriteTemplate st = level.getSpriteTemplate(x, y);
|
||||
|
||||
if (st != null) {
|
||||
if (st.lastVisibleTick != tick - 1) {
|
||||
if (st.sprite == null
|
||||
|| !sprites.contains(st.sprite)) {
|
||||
st.spawn(this, x, y, dir);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
st.lastVisibleTick = tick;
|
||||
}
|
||||
|
||||
if (dir != 0) {
|
||||
byte b = level.getBlock(x, y);
|
||||
if (((Level.TILE_BEHAVIORS[b & 0xff]) & Level.BIT_ANIMATED) > 0) {
|
||||
if ((b % 16) / 4 == 3 && b / 16 == 0) {
|
||||
if ((tick - x * 2) % 100 == 0) {
|
||||
xCannon = x;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
addSprite(new Sparkle(x * 16 + 8, y
|
||||
* 16
|
||||
+ (int) (Math.random() * 16),
|
||||
(float) Math.random() * dir, 0,
|
||||
0, 1, 5));
|
||||
}
|
||||
addSprite(new BulletBill(this, x * 16 + 8
|
||||
+ dir * 8, y * 16 + 15, dir));
|
||||
hasShotCannon = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasShotCannon) {
|
||||
sound.play(Art.samples[Art.SAMPLE_CANNON_FIRE],
|
||||
new FixedSoundSource(xCannon * 16, yCam + 120), 1, 1, 1);
|
||||
}
|
||||
|
||||
for (Sprite sprite : sprites) {
|
||||
sprite.tick();
|
||||
}
|
||||
|
||||
for (Sprite sprite : sprites) {
|
||||
sprite.collideCheck();
|
||||
}
|
||||
|
||||
for (Shell shell : shellsToCheck) {
|
||||
for (Sprite sprite : sprites) {
|
||||
if (sprite != shell && !shell.dead) {
|
||||
if (sprite.shellCollideCheck(shell)) {
|
||||
if (mario.carried == shell && !shell.dead) {
|
||||
mario.carried = null;
|
||||
shell.die();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
shellsToCheck.clear();
|
||||
|
||||
for (Fireball fireball : fireballsToCheck) {
|
||||
for (Sprite sprite : sprites) {
|
||||
if (sprite != fireball && !fireball.dead) {
|
||||
if (sprite.fireballCollideCheck(fireball)) {
|
||||
fireball.die();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fireballsToCheck.clear();
|
||||
}
|
||||
|
||||
sprites.addAll(0, spritesToAdd);
|
||||
sprites.removeAll(spritesToRemove);
|
||||
spritesToAdd.clear();
|
||||
spritesToRemove.clear();
|
||||
}
|
||||
|
||||
private DecimalFormat df = new DecimalFormat("00");
|
||||
private DecimalFormat df2 = new DecimalFormat("000");
|
||||
|
||||
public void render(Graphics g, float alpha) {
|
||||
int xCam = (int) (mario.xOld + (mario.x - mario.xOld) * alpha) - 160;
|
||||
int yCam = (int) (mario.yOld + (mario.y - mario.yOld) * alpha) - 120;
|
||||
|
||||
if (xCam < 0)
|
||||
xCam = 0;
|
||||
if (yCam < 0)
|
||||
yCam = 0;
|
||||
if (xCam > level.getWidth() * 16 - 320)
|
||||
xCam = level.getWidth() * 16 - 320;
|
||||
if (yCam > level.getHeight() * 16 - 240)
|
||||
yCam = level.getHeight() * 16 - 240;
|
||||
|
||||
// g.drawImage(Art.background, 0, 0, null);
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
bgLayer[i].setCam(xCam, yCam);
|
||||
bgLayer[i].render(g, tick, alpha);
|
||||
}
|
||||
|
||||
g.translate(-xCam, -yCam);
|
||||
for (Sprite sprite : sprites) {
|
||||
if (sprite.layer == 0)
|
||||
sprite.render(g, alpha);
|
||||
}
|
||||
g.translate(xCam, yCam);
|
||||
|
||||
// //////////THIS RENDERS THE LEVEL
|
||||
layer.setCam(xCam, yCam);
|
||||
layer.render(g, tick, paused ? 0 : alpha);
|
||||
layer.renderExit0(g, tick, paused ? 0 : alpha, mario.winTime == 0);
|
||||
// //////////END OF LEVEL RENDER
|
||||
|
||||
// //////////RENDERS SPRITES
|
||||
g.translate(-xCam, -yCam);
|
||||
for (Sprite sprite : sprites) {
|
||||
if (sprite.layer == 1)
|
||||
sprite.render(g, alpha);
|
||||
}
|
||||
g.translate(xCam, yCam);
|
||||
g.setColor(Color.BLACK);
|
||||
layer.renderExit1(g, tick, paused ? 0 : alpha);
|
||||
// //////////END OF SPRITE RENDERING
|
||||
|
||||
drawStringDropShadow(g, "MARIO " + df.format(Mario.lives), 0, 0, 7);
|
||||
// drawStringDropShadow(g, "00000000", 0, 1, 7);
|
||||
|
||||
drawStringDropShadow(g, "COIN", 14, 0, 7);
|
||||
drawStringDropShadow(g, " " + df.format(Mario.coins), 14, 1, 7);
|
||||
|
||||
drawStringDropShadow(g, "WORLD", 24, 0, 7);
|
||||
drawStringDropShadow(g, " " + Mario.levelString, 24, 1, 7);
|
||||
|
||||
drawStringDropShadow(g, "TIME", 35, 0, 7);
|
||||
int time = (timeLeft + 15 - 1) / 15;
|
||||
if (time < 0)
|
||||
time = 0;
|
||||
drawStringDropShadow(g, " " + df2.format(time), 35, 1, 7);
|
||||
|
||||
renderDirectionArrow(g);
|
||||
|
||||
if (startTime > 0) {
|
||||
float t = startTime + alpha - 2;
|
||||
t = t * t * 0.6f;
|
||||
renderBlackout(g, 160, 120, (int) (t));
|
||||
}
|
||||
// mario.x>level.xExit*16
|
||||
if (mario.winTime > 0) {
|
||||
float t = mario.winTime + alpha;
|
||||
t = t * t * 0.2f;
|
||||
|
||||
if (t > 0) {
|
||||
if (recorder != null) {
|
||||
recorder.stopRecord();
|
||||
recorder.levelWon();
|
||||
// recorder.printAll();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (t > 900) {
|
||||
|
||||
winActions();
|
||||
return;
|
||||
|
||||
// replayer = new Replayer(recorder.getBytes());
|
||||
// init();
|
||||
}
|
||||
|
||||
renderBlackout(g, (int) (mario.xDeathPos - xCam),
|
||||
(int) (mario.yDeathPos - yCam), (int) (320 - t));
|
||||
}
|
||||
|
||||
if (mario.deathTime > 0) {
|
||||
g.setColor(Color.BLACK);
|
||||
float t = mario.deathTime + alpha;
|
||||
t = t * t * 0.4f;
|
||||
|
||||
if (t > 0 && Mario.lives <= 0) {
|
||||
if (recorder != null) {
|
||||
recorder.stopRecord();
|
||||
}
|
||||
}
|
||||
|
||||
if (t > 1800) {
|
||||
Mario.lives--;
|
||||
deathActions();
|
||||
}
|
||||
|
||||
renderBlackout(g, (int) (mario.xDeathPos - xCam),
|
||||
(int) (mario.yDeathPos - yCam), (int) (320 - t));
|
||||
}
|
||||
}
|
||||
|
||||
public void winActions() {
|
||||
|
||||
}
|
||||
|
||||
public void deathActions() {
|
||||
|
||||
}
|
||||
|
||||
protected void reset() {
|
||||
paused = false;
|
||||
Sprite.spriteContext = this;
|
||||
sprites.clear();
|
||||
|
||||
try {
|
||||
level = currentLevel.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
level.resetSpriteTemplate();
|
||||
|
||||
layer = new LevelRenderer(level, graphicsConfiguration, 320, 240);
|
||||
|
||||
mario = new Mario(this);
|
||||
sprites.add(mario);
|
||||
startTime = 1;
|
||||
|
||||
timeLeft = 200 * 15;
|
||||
Art.startMusic(1);
|
||||
tick = 0;
|
||||
|
||||
if (recorder != null) {
|
||||
recorder.detailedLog = "";
|
||||
}
|
||||
gameStarted = false;
|
||||
}
|
||||
|
||||
private void renderDirectionArrow(Graphics g) {
|
||||
if (widthArrow < 0)
|
||||
g.setColor(new Color(0, 0, 255, 150));
|
||||
else
|
||||
g.setColor(new Color(255, 0, 0, 150));
|
||||
|
||||
g.fillPolygon(xPositionsArrow, yPositionsArrow,
|
||||
Math.min(xPositionsArrow.length, yPositionsArrow.length));
|
||||
g.setColor(new Color(0, 0, 0, 255));
|
||||
g.drawPolygon(xPositionsArrow, yPositionsArrow,
|
||||
Math.min(xPositionsArrow.length, yPositionsArrow.length));
|
||||
}
|
||||
|
||||
private void drawStringDropShadow(Graphics g, String text, int x, int y,
|
||||
int c) {
|
||||
drawString(g, text, x * 8 + 5, y * 8 + 5, 0);
|
||||
drawString(g, text, x * 8 + 4, y * 8 + 4, c);
|
||||
}
|
||||
|
||||
private void drawString(Graphics g, String text, int x, int y, int c) {
|
||||
char[] ch = text.toCharArray();
|
||||
for (int i = 0; i < ch.length; i++) {
|
||||
g.drawImage(Art.font[ch[i] - 32][c], x + i * 8, y, null);
|
||||
}
|
||||
}
|
||||
|
||||
float decrease = (float) 0.03;
|
||||
float factor = 0;
|
||||
boolean in = true;
|
||||
String flipText = "FLIP! MOVE THE OTHER WAY!";
|
||||
|
||||
private void renderBlackout(Graphics g, int x, int y, int radius) {
|
||||
if (radius > 320)
|
||||
return;
|
||||
|
||||
int[] xp = new int[20];
|
||||
int[] yp = new int[20];
|
||||
for (int i = 0; i < 16; i++) {
|
||||
xp[i] = x + (int) (Math.cos(i * Math.PI / 15) * radius);
|
||||
yp[i] = y + (int) (Math.sin(i * Math.PI / 15) * radius);
|
||||
}
|
||||
xp[16] = 320;
|
||||
yp[16] = y;
|
||||
xp[17] = 320;
|
||||
yp[17] = 240;
|
||||
xp[18] = 0;
|
||||
yp[18] = 240;
|
||||
xp[19] = 0;
|
||||
yp[19] = y;
|
||||
g.fillPolygon(xp, yp, xp.length);
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
xp[i] = x - (int) (Math.cos(i * Math.PI / 15) * radius);
|
||||
yp[i] = y - (int) (Math.sin(i * Math.PI / 15) * radius);
|
||||
}
|
||||
xp[16] = 320;
|
||||
yp[16] = y;
|
||||
xp[17] = 320;
|
||||
yp[17] = 0;
|
||||
xp[18] = 0;
|
||||
yp[18] = 0;
|
||||
xp[19] = 0;
|
||||
yp[19] = y;
|
||||
|
||||
g.fillPolygon(xp, yp, xp.length);
|
||||
}
|
||||
|
||||
public void addSprite(Sprite sprite) {
|
||||
spritesToAdd.add(sprite);
|
||||
sprite.tick();
|
||||
}
|
||||
|
||||
public void removeSprite(Sprite sprite) {
|
||||
spritesToRemove.add(sprite);
|
||||
}
|
||||
|
||||
public float getX(float alpha) {
|
||||
int xCam = (int) (mario.xOld + (mario.x - mario.xOld) * alpha) - 160;
|
||||
|
||||
if (xCam < 0)
|
||||
xCam = 0;
|
||||
|
||||
return xCam + 160;
|
||||
}
|
||||
|
||||
public float getY(float alpha) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void bump(int x, int y, boolean canBreakBricks) {
|
||||
byte block = level.getBlock(x, y);
|
||||
|
||||
if ((Level.TILE_BEHAVIORS[block & 0xff] & Level.BIT_BUMPABLE) > 0) {
|
||||
bumpInto(x, y - 1);
|
||||
level.setBlock(x, y, (byte) 4);
|
||||
|
||||
if (((Level.TILE_BEHAVIORS[block & 0xff]) & Level.BIT_SPECIAL) > 0) {
|
||||
sound.play(Art.samples[Art.SAMPLE_ITEM_SPROUT],
|
||||
new FixedSoundSource(x * 16 + 8, y * 16 + 8), 1, 1, 1);
|
||||
if (!Mario.large) {
|
||||
addSprite(new Mushroom(this, x * 16 + 8, y * 16 + 8));
|
||||
} else {
|
||||
addSprite(new FireFlower(this, x * 16 + 8, y * 16 + 8));
|
||||
}
|
||||
|
||||
if (recorder != null) {
|
||||
recorder.blockPowerDestroyRecord();
|
||||
}
|
||||
} else {
|
||||
if (recorder != null) {
|
||||
recorder.blockCoinDestroyRecord();
|
||||
}
|
||||
|
||||
Mario.getCoin();
|
||||
sound.play(Art.samples[Art.SAMPLE_GET_COIN],
|
||||
new FixedSoundSource(x * 16 + 8, y * 16 + 8), 1, 1, 1);
|
||||
addSprite(new CoinAnim(x, y));
|
||||
}
|
||||
}
|
||||
|
||||
if ((Level.TILE_BEHAVIORS[block & 0xff] & Level.BIT_BREAKABLE) > 0) {
|
||||
bumpInto(x, y - 1);
|
||||
if (canBreakBricks) {
|
||||
if (recorder != null) {
|
||||
recorder.blockEmptyDestroyRecord();
|
||||
}
|
||||
|
||||
sound.play(Art.samples[Art.SAMPLE_BREAK_BLOCK],
|
||||
new FixedSoundSource(x * 16 + 8, y * 16 + 8), 1, 1, 1);
|
||||
level.setBlock(x, y, (byte) 0);
|
||||
for (int xx = 0; xx < 2; xx++)
|
||||
for (int yy = 0; yy < 2; yy++)
|
||||
addSprite(new Particle(x * 16 + xx * 8 + 4, y * 16 + yy
|
||||
* 8 + 4, (xx * 2 - 1) * 4, (yy * 2 - 1) * 4 - 8));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void bumpInto(int x, int y) {
|
||||
byte block = level.getBlock(x, y);
|
||||
if (((Level.TILE_BEHAVIORS[block & 0xff]) & Level.BIT_PICKUPABLE) > 0) {
|
||||
Mario.getCoin();
|
||||
sound.play(Art.samples[Art.SAMPLE_GET_COIN], new FixedSoundSource(
|
||||
x * 16 + 8, y * 16 + 8), 1, 1, 1);
|
||||
level.setBlock(x, y, (byte) 0);
|
||||
addSprite(new CoinAnim(x, y + 1));
|
||||
|
||||
// TODO no idea when this happens... maybe remove coin count
|
||||
if (recorder != null)
|
||||
recorder.recordCoin();
|
||||
}
|
||||
|
||||
for (Sprite sprite : sprites) {
|
||||
sprite.bumpCheck(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
public void setLevel(Level level) {
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent me) {
|
||||
}
|
||||
}
|
||||
198
src/dk/itu/mario/scene/LevelSceneCustom.java
Normal file
198
src/dk/itu/mario/scene/LevelSceneCustom.java
Normal file
@@ -0,0 +1,198 @@
|
||||
package dk.itu.mario.scene;
|
||||
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import dk.itu.mario.MarioInterface.GamePlay;
|
||||
import dk.itu.mario.MarioInterface.LevelGenerator;
|
||||
import dk.itu.mario.engine.Art;
|
||||
import dk.itu.mario.engine.BgRenderer;
|
||||
import dk.itu.mario.engine.DataRecorder;
|
||||
import dk.itu.mario.engine.LevelRenderer;
|
||||
import dk.itu.mario.engine.MarioComponent;
|
||||
import dk.itu.mario.engine.sonar.FixedSoundSource;
|
||||
import dk.itu.mario.engine.sprites.CoinAnim;
|
||||
import dk.itu.mario.engine.sprites.FireFlower;
|
||||
import dk.itu.mario.engine.sprites.Mario;
|
||||
import dk.itu.mario.engine.sprites.Mushroom;
|
||||
import dk.itu.mario.engine.sprites.Particle;
|
||||
import dk.itu.mario.engine.sprites.Sprite;
|
||||
import dk.itu.mario.engine.util.FileHandler;
|
||||
import dk.itu.mario.level.BgLevelGenerator;
|
||||
import dk.itu.mario.level.Level;
|
||||
import dk.itu.mario.level.RandomLevel;
|
||||
|
||||
public class LevelSceneCustom extends LevelScene {
|
||||
private boolean isCustom;
|
||||
private LevelGenerator clg;
|
||||
|
||||
public LevelSceneCustom(GraphicsConfiguration graphicsConfiguration,
|
||||
MarioComponent renderer, long seed, int levelDifficulty, int type,
|
||||
boolean isCustom, LevelGenerator levelGenerator) {
|
||||
super(graphicsConfiguration, renderer, seed, levelDifficulty, type);
|
||||
this.isCustom = isCustom;
|
||||
this.clg = levelGenerator;
|
||||
}
|
||||
|
||||
public void init() {
|
||||
try {
|
||||
Level.loadBehaviors(new DataInputStream(LevelSceneCustom.class
|
||||
.getResourceAsStream("/res/tiles.dat")));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
//if (level == null)
|
||||
// if (isCustom) {
|
||||
GamePlay gp = GamePlay.read("player.txt");
|
||||
currentLevel = (Level) clg.generateLevel(gp);
|
||||
|
||||
// You can use the following commands if you want to benefit
|
||||
// from
|
||||
// the interface containing detailed information
|
||||
String detailedInfo = FileHandler.readFile("DetailedInfo.txt");
|
||||
System.out.println("DetailedInfo: " + detailedInfo);
|
||||
// } else
|
||||
// currentLevel = new RandomLevel(320, 15, levelSeed,
|
||||
// levelDifficulty, levelType);
|
||||
|
||||
try {
|
||||
level = currentLevel.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// level is always overground
|
||||
Art.startMusic(1);
|
||||
|
||||
paused = false;
|
||||
Sprite.spriteContext = this;
|
||||
sprites.clear();
|
||||
|
||||
layer = new LevelRenderer(level, graphicsConfiguration, 320, 240);
|
||||
for (int i = 0; i < 2; i++) {
|
||||
int scrollSpeed = 4 >> i;
|
||||
int w = ((level.getWidth() * 16) - 320) / scrollSpeed + 320;
|
||||
int h = ((level.getHeight() * 16) - 240) / scrollSpeed + 240;
|
||||
Level bgLevel = BgLevelGenerator.createLevel(w / 32 + 1,
|
||||
h / 32 + 1, i == 0, levelType);
|
||||
bgLayer[i] = new BgRenderer(bgLevel, graphicsConfiguration, 320,
|
||||
240, scrollSpeed);
|
||||
}
|
||||
|
||||
mario = new Mario(this);
|
||||
sprites.add(mario);
|
||||
startTime = 1;
|
||||
|
||||
timeLeft = 200 * 15;
|
||||
|
||||
tick = 0;
|
||||
|
||||
if (!isCustom && recorder == null)
|
||||
recorder = new DataRecorder(this, (RandomLevel) level, keys);
|
||||
|
||||
gameStarted = false;
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
super.tick();
|
||||
|
||||
if (recorder != null && !gameStarted) {
|
||||
recorder.startLittleRecord();
|
||||
recorder.startTime();
|
||||
gameStarted = true;
|
||||
}
|
||||
if (recorder != null)
|
||||
recorder.tickRecord();
|
||||
}
|
||||
|
||||
public void winActions() {
|
||||
if (recorder != null)
|
||||
recorder.fillGamePlayMetrics((RandomLevel) level);
|
||||
|
||||
marioComponent.win();
|
||||
}
|
||||
|
||||
public void deathActions() {
|
||||
if (Mario.lives <= 0) {// has no more lives
|
||||
if (recorder != null)
|
||||
recorder.fillGamePlayMetrics((RandomLevel) level);
|
||||
marioComponent.lose();
|
||||
} else
|
||||
// mario still has lives to play :)--> have a new beginning
|
||||
reset();
|
||||
}
|
||||
|
||||
public void bump(int x, int y, boolean canBreakBricks) {
|
||||
byte block = level.getBlock(x, y);
|
||||
|
||||
if ((Level.TILE_BEHAVIORS[block & 0xff] & Level.BIT_BUMPABLE) > 0) {
|
||||
bumpInto(x, y - 1);
|
||||
level.setBlock(x, y, (byte) 4);
|
||||
|
||||
if (((Level.TILE_BEHAVIORS[block & 0xff]) & Level.BIT_SPECIAL) > 0) {
|
||||
sound.play(Art.samples[Art.SAMPLE_ITEM_SPROUT],
|
||||
new FixedSoundSource(x * 16 + 8, y * 16 + 8), 1, 1, 1);
|
||||
if (!Mario.large) {
|
||||
addSprite(new Mushroom(this, x * 16 + 8, y * 16 + 8));
|
||||
} else {
|
||||
addSprite(new FireFlower(this, x * 16 + 8, y * 16 + 8));
|
||||
}
|
||||
|
||||
if (recorder != null) {
|
||||
recorder.blockPowerDestroyRecord();
|
||||
}
|
||||
} else {
|
||||
// TODO should only record hidden coins (in boxes)
|
||||
if (recorder != null) {
|
||||
recorder.blockCoinDestroyRecord();
|
||||
}
|
||||
|
||||
Mario.getCoin();
|
||||
sound.play(Art.samples[Art.SAMPLE_GET_COIN],
|
||||
new FixedSoundSource(x * 16 + 8, y * 16 + 8), 1, 1, 1);
|
||||
addSprite(new CoinAnim(x, y));
|
||||
}
|
||||
}
|
||||
|
||||
if ((Level.TILE_BEHAVIORS[block & 0xff] & Level.BIT_BREAKABLE) > 0) {
|
||||
bumpInto(x, y - 1);
|
||||
if (canBreakBricks) {
|
||||
if (recorder != null) {
|
||||
recorder.blockEmptyDestroyRecord();
|
||||
}
|
||||
|
||||
sound.play(Art.samples[Art.SAMPLE_BREAK_BLOCK],
|
||||
new FixedSoundSource(x * 16 + 8, y * 16 + 8), 1, 1, 1);
|
||||
level.setBlock(x, y, (byte) 0);
|
||||
for (int xx = 0; xx < 2; xx++)
|
||||
for (int yy = 0; yy < 2; yy++)
|
||||
addSprite(new Particle(x * 16 + xx * 8 + 4, y * 16 + yy
|
||||
* 8 + 4, (xx * 2 - 1) * 4, (yy * 2 - 1) * 4 - 8));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void bumpInto(int x, int y) {
|
||||
byte block = level.getBlock(x, y);
|
||||
if (((Level.TILE_BEHAVIORS[block & 0xff]) & Level.BIT_PICKUPABLE) > 0) {
|
||||
Mario.getCoin();
|
||||
sound.play(Art.samples[Art.SAMPLE_GET_COIN], new FixedSoundSource(
|
||||
x * 16 + 8, y * 16 + 8), 1, 1, 1);
|
||||
level.setBlock(x, y, (byte) 0);
|
||||
addSprite(new CoinAnim(x, y + 1));
|
||||
|
||||
// TODO no idea when this happens... maybe remove coin count
|
||||
if (recorder != null)
|
||||
recorder.recordCoin();
|
||||
}
|
||||
|
||||
for (Sprite sprite : sprites) {
|
||||
sprite.bumpCheck(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
62
src/dk/itu/mario/scene/LoseScene.java
Normal file
62
src/dk/itu/mario/scene/LoseScene.java
Normal file
@@ -0,0 +1,62 @@
|
||||
package dk.itu.mario.scene;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
import dk.itu.mario.engine.Art;
|
||||
import dk.itu.mario.engine.sprites.Mario;
|
||||
|
||||
public class LoseScene extends Scene {
|
||||
|
||||
private int tick;
|
||||
private String scrollMessage = "Game over!";
|
||||
|
||||
public LoseScene() {
|
||||
}
|
||||
|
||||
public void init() {
|
||||
}
|
||||
|
||||
public void render(Graphics g, float alpha) {
|
||||
g.setColor(Color.decode("#a07070"));
|
||||
g.fillRect(0, 0, 320, 240);
|
||||
int f = tick / 3 % 10;
|
||||
if (f >= 6)
|
||||
f = 10 - f;
|
||||
g.drawImage(Art.gameOver[f][0], 160 - 48, 100 - 32, null);
|
||||
drawString(g, scrollMessage, 160 - scrollMessage.length() * 4, 160, 0);
|
||||
}
|
||||
|
||||
private void drawString(Graphics g, String text, int x, int y, int c) {
|
||||
char[] ch = text.toCharArray();
|
||||
for (int i = 0; i < ch.length; i++) {
|
||||
g.drawImage(Art.font[ch[i] - 32][c], x + i * 8, y, null);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean wasDown = true;
|
||||
|
||||
public void tick() {
|
||||
tick++;
|
||||
if (!wasDown && keys[Mario.KEY_JUMP]) {
|
||||
// component.toTitle();
|
||||
}
|
||||
if (keys[Mario.KEY_JUMP]) {
|
||||
wasDown = false;
|
||||
}
|
||||
}
|
||||
|
||||
public float getX(float alpha) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public float getY(float alpha) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent me) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
}
|
||||
43
src/dk/itu/mario/scene/Scene.java
Normal file
43
src/dk/itu/mario/scene/Scene.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package dk.itu.mario.scene;
|
||||
|
||||
import java.awt.Graphics;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
|
||||
import dk.itu.mario.engine.sonar.SonarSoundEngine;
|
||||
import dk.itu.mario.engine.sonar.SoundListener;
|
||||
|
||||
|
||||
public abstract class Scene implements SoundListener
|
||||
{
|
||||
public SonarSoundEngine sound;
|
||||
public static boolean[] keys = new boolean[16];
|
||||
|
||||
public static final int COLOR_BLACK = 0;
|
||||
public static final int COLOR_RED = 1;
|
||||
public static final int COLOR_GREEN = 2;
|
||||
public static final int COLOR_BLUE = 3;
|
||||
public static final int COLOR_YELLOW = 4;
|
||||
public static final int COLOR_PURPLE = 5;
|
||||
public static final int COLOR_LIGHTBLUE = 6;
|
||||
public static final int COLOR_WHITE = 7;
|
||||
|
||||
public void toggleKey(int key, boolean isPressed)
|
||||
{
|
||||
keys[key] = isPressed;
|
||||
}
|
||||
|
||||
public final void setSound(SonarSoundEngine sound)
|
||||
{
|
||||
sound.setListener(this);
|
||||
this.sound = sound;
|
||||
}
|
||||
|
||||
public abstract void mouseClicked(MouseEvent me);
|
||||
|
||||
public abstract void init();
|
||||
|
||||
public abstract void tick();
|
||||
|
||||
public abstract void render(Graphics og, float alpha);
|
||||
}
|
||||
58
src/dk/itu/mario/scene/WinScene.java
Normal file
58
src/dk/itu/mario/scene/WinScene.java
Normal file
@@ -0,0 +1,58 @@
|
||||
package dk.itu.mario.scene;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
import dk.itu.mario.engine.Art;
|
||||
import dk.itu.mario.engine.sprites.Mario;
|
||||
|
||||
public class WinScene extends Scene {
|
||||
private int tick;
|
||||
private String scrollMessage = "Thank you for saving me, Mario!";
|
||||
|
||||
public WinScene() {
|
||||
}
|
||||
|
||||
public void init() {
|
||||
}
|
||||
|
||||
public void render(Graphics g, float alpha) {
|
||||
g.setColor(Color.decode("#8080a0"));
|
||||
g.fillRect(0, 0, 320, 240);
|
||||
g.drawImage(Art.endScene[tick / 24 % 2][0], 160 - 48, 100 - 48, null);
|
||||
drawString(g, scrollMessage, 160 - scrollMessage.length() * 4, 160, 0);
|
||||
}
|
||||
|
||||
private void drawString(Graphics g, String text, int x, int y, int c) {
|
||||
char[] ch = text.toCharArray();
|
||||
for (int i = 0; i < ch.length; i++) {
|
||||
g.drawImage(Art.font[ch[i] - 32][c], x + i * 8, y, null);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean wasDown = true;
|
||||
|
||||
public void tick() {
|
||||
tick++;
|
||||
if (!wasDown && keys[Mario.KEY_JUMP]) {
|
||||
// component.toTitle();
|
||||
}
|
||||
if (keys[Mario.KEY_JUMP]) {
|
||||
wasDown = false;
|
||||
}
|
||||
}
|
||||
|
||||
public float getX(float alpha) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public float getY(float alpha) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent me) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user