Initial game engine.
18
.classpath
@@ -1,22 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<classpath>
|
<classpath>
|
||||||
<classpathentry kind="src" path="test"/>
|
|
||||||
<classpathentry excluding="bin|src/|test/" kind="src" path=""/>
|
|
||||||
<classpathentry kind="src" path="src"/>
|
<classpathentry kind="src" path="src"/>
|
||||||
<classpathentry kind="lib" path="lib/jdom.jar"/>
|
|
||||||
<classpathentry kind="lib" path="lib/junit-4.10.jar"/>
|
|
||||||
<classpathentry kind="lib" path="lib/slf4j-api-1.6.4.jar"/>
|
|
||||||
<classpathentry kind="lib" path="lib/xuggle-xuggler.jar"/>
|
|
||||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||||
<classpathentry kind="lib" path="lib/drools-compiler-5.3.0.Final.jar"/>
|
<classpathentry kind="output" path="bin"/>
|
||||||
<classpathentry kind="lib" path="lib/drools-core-5.3.0.Final.jar"/>
|
|
||||||
<classpathentry kind="lib" path="lib/drools-decisiontables-5.3.0.Final.jar"/>
|
|
||||||
<classpathentry kind="lib" path="lib/drools-jsr94-5.3.0.Final.jar"/>
|
|
||||||
<classpathentry kind="lib" path="lib/drools-api-5.2.0.M1.jar"/>
|
|
||||||
<classpathentry kind="lib" path="lib/xstream-1.4.2.jar"/>
|
|
||||||
<classpathentry kind="lib" path="lib/knowledge-api-5.3.0.Final.jar"/>
|
|
||||||
<classpathentry kind="lib" path="lib/ecj.jar"/>
|
|
||||||
<classpathentry kind="lib" path="lib/antlr-3.4-complete-no-antlrv2.jar"/>
|
|
||||||
<classpathentry kind="lib" path="lib/mvel2-2.1.Beta8.jar"/>
|
|
||||||
<classpathentry kind="output" path="classes"/>
|
|
||||||
</classpath>
|
</classpath>
|
||||||
|
|||||||
14
.gitignore
vendored
@@ -1,14 +0,0 @@
|
|||||||
bin
|
|
||||||
|
|
||||||
build
|
|
||||||
|
|
||||||
classes
|
|
||||||
|
|
||||||
dist
|
|
||||||
|
|
||||||
docs
|
|
||||||
|
|
||||||
player.txt
|
|
||||||
DetailedInfo.txt
|
|
||||||
DetailedInfo.xml
|
|
||||||
*.png
|
|
||||||
2
.project
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<projectDescription>
|
<projectDescription>
|
||||||
<name>cs8803p3</name>
|
<name>SuperPuzzle</name>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
<projects>
|
<projects>
|
||||||
</projects>
|
</projects>
|
||||||
|
|||||||
12
README.TXT
@@ -1,12 +0,0 @@
|
|||||||
Adaptive Mario Instructions
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
Unzip the attached archive 'CS8803_P3.zip' and change to the new directory.
|
|
||||||
|
|
||||||
To build Adaptive Mario: run 'ant clean' then 'ant' in this directory.
|
|
||||||
|
|
||||||
To run Adaptive Mario: change to the 'dist' directory, then run java -jar CS8803_P3.jar
|
|
||||||
|
|
||||||
For full instructions, see writeup/CS8803_P3.PDF.
|
|
||||||
|
|
||||||
For assistance, please contact Woody Folsom <woody.folsom@gatech.edu> or Marshall Gillson <mgillson1@gmail.com>.
|
|
||||||
104
build.xml
@@ -1,104 +0,0 @@
|
|||||||
<project name="CS8803_P3" default="dist" basedir=".">
|
|
||||||
<description>
|
|
||||||
simple example build file
|
|
||||||
</description>
|
|
||||||
|
|
||||||
<!-- set global properties for this build -->
|
|
||||||
<property name="build" location="classes" />
|
|
||||||
<property name="dist" location="dist" />
|
|
||||||
<property name="docs" location="docs" />
|
|
||||||
<property name="grammars" location="grammars" />
|
|
||||||
<property name="lib" location="lib" />
|
|
||||||
<property name="res" location="res" />
|
|
||||||
<property name="rules" location="rules" />
|
|
||||||
<property name="project.name" value="CS8803_P3" />
|
|
||||||
<property name="src" location="src" />
|
|
||||||
<property name="test" location="test" />
|
|
||||||
|
|
||||||
<path id="build.classpath">
|
|
||||||
<fileset dir="${lib}">
|
|
||||||
<include name="**/*.jar" />
|
|
||||||
</fileset>
|
|
||||||
</path>
|
|
||||||
|
|
||||||
<path id="classpath.test">
|
|
||||||
<path refid="build.classpath" />
|
|
||||||
<pathelement location="lib/junit-4.10.jar" />
|
|
||||||
<pathelement location="${build}" />
|
|
||||||
</path>
|
|
||||||
|
|
||||||
<target name="clean" description="clean up">
|
|
||||||
<!-- Delete the ${build} and ${dist} directory trees -->
|
|
||||||
<delete dir="${build}" />
|
|
||||||
<delete dir="${dist}" />
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="compile" depends="copy-resources">
|
|
||||||
<!-- Compile the java code from ${src} into ${build} -->
|
|
||||||
<javac srcdir="${src}" destdir="${build}" classpathref="build.classpath" debug="true" source="1.6" target="1.6"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="compile-test" depends="compile">
|
|
||||||
<javac srcdir="${test}" destdir="${build}" debug="true">
|
|
||||||
<classpath refid="classpath.test"/>
|
|
||||||
</javac>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="copy-resources" depends="init" >
|
|
||||||
<copy todir="${build}/res">
|
|
||||||
<fileset dir="${res}">
|
|
||||||
<include name="**/*" />
|
|
||||||
</fileset>
|
|
||||||
</copy>
|
|
||||||
<copy todir="${dist}/grammars">
|
|
||||||
<fileset dir="${grammars}">
|
|
||||||
<include name="**/*" />
|
|
||||||
</fileset>
|
|
||||||
</copy>
|
|
||||||
<copy todir="${dist}/rules">
|
|
||||||
<fileset dir="${rules}">
|
|
||||||
<include name="**/*" />
|
|
||||||
</fileset>
|
|
||||||
</copy>
|
|
||||||
<copy file="DetailedInfo.txt" todir="${dist}" failonerror="false" overwrite="true"/>
|
|
||||||
<copy file="player.txt" todir="${dist}" failonerror="false" overwrite="true" />
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="dist" depends="copy-resources, compile"
|
|
||||||
description="generate the distribution">
|
|
||||||
<jar jarfile="${dist}/${project.name}.jar">
|
|
||||||
<fileset dir="${build}" excludes="**/*Test.class" />
|
|
||||||
<manifest>
|
|
||||||
<attribute name="Main-Class" value="dk.itu.mario.engine.Play" />
|
|
||||||
<attribute name="Class-Path" value="../lib/antlr-3.4-complete-no-antlrv2.jar ../lib/drools-api-5.2.0.M1.jar.jar ../lib/drools-compiler-5.3.0.Final.jar ../lib/drools-core-5.3.0.Final.jar ../lib/drools-decisiontables-5.3.0.Final.jar ../lib/drools-jsr94-5.3.0.Final.jar ../lib/ecj.jar ../lib/jdom.jar ../lib/knowledge-api-5.3.0.Final.jar ../lib/mvel2-2.1.Beta8.jar ../lib/slf4j-api-1.6.4.jar ../lib/xstream-1.4.2.jar ../lib/xuggle-xuggler.jar" />
|
|
||||||
</manifest>
|
|
||||||
</jar>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<!-- Creates Javadoc -->
|
|
||||||
<target name="docs" depends="compile">
|
|
||||||
<javadoc packagenames="src" sourcepath="${src}" destdir="${docs}">
|
|
||||||
<!-- Define which files / directory should get included, we include all -->
|
|
||||||
<fileset dir="${src}">
|
|
||||||
<include name="**" />
|
|
||||||
</fileset>
|
|
||||||
</javadoc>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="init">
|
|
||||||
<!-- Create the time stamp -->
|
|
||||||
<tstamp />
|
|
||||||
<!-- Create the build directory structure used by compile -->
|
|
||||||
<mkdir dir="${build}" />
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="test" depends="compile-test">
|
|
||||||
<junit haltonfailure="true">
|
|
||||||
<classpath refid="classpath.test" />
|
|
||||||
<formatter type="brief" usefile="false" />
|
|
||||||
<batchtest>
|
|
||||||
<fileset dir="${build}" includes="**/*Test.class" />
|
|
||||||
</batchtest>
|
|
||||||
</junit>
|
|
||||||
</target>
|
|
||||||
</project>
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
#VAR name = LevelComponent.TYPE
|
|
||||||
VAR S = LEVEL
|
|
||||||
VAR LAND_SEGMENT = LEVEL_SEGMENT
|
|
||||||
VAR LO_HI = LO_HI
|
|
||||||
VAR HI_LO = HI_LO
|
|
||||||
VAR LO_PATH = LO_PATH
|
|
||||||
VAR HI_PATH = HI_PATH
|
|
||||||
VAR lo_path = FLAT_LO
|
|
||||||
VAR hi_path = FLAT_HI
|
|
||||||
|
|
||||||
###
|
|
||||||
#Coin Dive (Some empty blocks. The user climbs them and runs off; coins line their path as they fall back to the ground.)
|
|
||||||
#Free power-up. (Sets the player up to get a power-up with little or no challenge.)
|
|
||||||
#Straight. (A straight stretch of land with maybe one enemy and maybe some coins or blocks.)
|
|
||||||
#Single Pit (A pit that the user must jump over; rocks on either side.)
|
|
||||||
#Bowling Alley (A red koopa right before a long line of enemies. Kill them all in a row by throwing the shell.)
|
|
||||||
#Cannon Line (A stack of 2-3 canons.)
|
|
||||||
#Maze (A... y’know... maze.)
|
|
||||||
#Lemming Trap (A little pit with a few enemies that jump down into it.)
|
|
||||||
#Platform Jump (A bunch of platforms to jump between.)
|
|
||||||
#Pipe Jump (A bunch of thin pipes to jump between. This can be rendered much easier, because sometimes the space between the pipes is filled.)
|
|
||||||
###
|
|
||||||
|
|
||||||
VAR coin_dive = COIN_DIVE
|
|
||||||
VAR power_up = POWER_UP
|
|
||||||
VAR single_pit = SINGLE_PIT
|
|
||||||
VAR bowling_alley = BOWLING_ALLEY
|
|
||||||
VAR cannon_line = CANNON_LINE
|
|
||||||
VAR maze = MAZE
|
|
||||||
VAR lemming_trap = LEMMING_TRAP
|
|
||||||
VAR platform_jump = PLATFORM_JUMP
|
|
||||||
VAR pipe_jump = PIPE_JUMP
|
|
||||||
VAR CHALLENGE = CHALLENGE
|
|
||||||
|
|
||||||
#RULE name -> {probabilities}, (clause) [+,|] (clause)...
|
|
||||||
RULE S -> LAND_SEGMENT + LAND_SEGMENT
|
|
||||||
RULE LAND_SEGMENT -> {0.25,0.65,0.10}, (LO_HI + HI_LO) | (LO_PATH) | (LAND_SEGMENT + LAND_SEGMENT)
|
|
||||||
RULE LO_HI -> LO_PATH + CHALLENGE
|
|
||||||
RULE HI_LO -> CHALLENGE + LO_PATH
|
|
||||||
#RULE HI_PATH -> {0.10,0.60,0.30}, (HI_PATH + HI_PATH) | (hi_path + CHALLENGE + hi_path) | (hi_path)
|
|
||||||
RULE LO_PATH -> {0.10,0.60,0.30}, (LO_PATH + LO_PATH) | (lo_path + CHALLENGE + lo_path) | (lo_path)
|
|
||||||
RULE CHALLENGE -> {0.10,0.10,0.10,0.10,0.10,0.10,0.10,0.10,0.10,0.10}, coin_dive | power_up | lo_path | single_pit | bowling_alley | cannon_line | maze | lemming_trap | platform_jump | pipe_jump
|
|
||||||
|
|
||||||
#START variable name
|
|
||||||
START = S
|
|
||||||
BIN
lib/ecj.jar
BIN
lib/jdom.jar
@@ -1 +0,0 @@
|
|||||||
Placeholder.
|
|
||||||
BIN
res/Thumbs.db
BIN
res/abkey.png
|
Before Width: | Height: | Size: 2.4 KiB |
BIN
res/bgsheet.png
|
Before Width: | Height: | Size: 15 KiB |
BIN
res/endscene.gif
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 5.9 KiB |
BIN
res/font.gif
|
Before Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
BIN
res/keys.png
|
Before Width: | Height: | Size: 3.3 KiB |
BIN
res/logo.gif
|
Before Width: | Height: | Size: 2.7 KiB |
BIN
res/mapsheet.png
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
BIN
res/snd/1-up.wav
BIN
res/snd/bump.wav
BIN
res/snd/coin.wav
BIN
res/snd/exit.wav
BIN
res/snd/jump.wav
BIN
res/snd/kick.wav
BIN
res/snd/pipe.wav
BIN
res/test.lvl
BIN
res/tiles.dat
BIN
res/title.gif
|
Before Width: | Height: | Size: 6.4 KiB |
BIN
res/tweak.gif
|
Before Width: | Height: | Size: 4.2 KiB |
BIN
res/worldmap.png
|
Before Width: | Height: | Size: 10 KiB |
@@ -1,33 +0,0 @@
|
|||||||
package dk.itu.mario.level;
|
|
||||||
|
|
||||||
rule "NoviceJumper"
|
|
||||||
when
|
|
||||||
playerProfile : PlayerProfile( jumpSkill <= 20 ) // condition
|
|
||||||
then
|
|
||||||
System.out.println("PlayerProfile indicates NoviceJumper. Disabling Pipe challenge."); // consequence
|
|
||||||
playerProfile.setDisabled(LevelComponent.TYPE.PIPE_JUMP);
|
|
||||||
end
|
|
||||||
|
|
||||||
rule "BeginnerJumper"
|
|
||||||
when
|
|
||||||
playerProfile : PlayerProfile( jumpSkill > 20 ) // condition
|
|
||||||
then
|
|
||||||
System.out.println("PlayerProfile indicates Beginner (or better) Jumper. Pipe challenge enabled!"); // consequence
|
|
||||||
playerProfile.setEnabled(LevelComponent.TYPE.PIPE_JUMP);
|
|
||||||
end
|
|
||||||
|
|
||||||
rule "NoviceRunner"
|
|
||||||
when
|
|
||||||
playerProfile : PlayerProfile( runSkill <= 20 ) // condition
|
|
||||||
then
|
|
||||||
System.out.println("PlayerProfile indicates NoviceRunner. Disabling Maze challenge."); // consequence
|
|
||||||
playerProfile.setDisabled(LevelComponent.TYPE.MAZE);
|
|
||||||
end
|
|
||||||
|
|
||||||
rule "BeginnerRunner"
|
|
||||||
when
|
|
||||||
playerProfile : PlayerProfile( runSkill > 20 ) // condition
|
|
||||||
then
|
|
||||||
System.out.println("PlayerProfile indicates Beginner (or better) Runner. Maze challenge enabled!"); // consequence
|
|
||||||
playerProfile.setEnabled(LevelComponent.TYPE.MAZE);
|
|
||||||
end
|
|
||||||
BIN
src/dk/itu/.DS_Store
vendored
BIN
src/dk/itu/mario/.DS_Store
vendored
BIN
src/dk/itu/mario/MarioInterface/.DS_Store
vendored
@@ -1,10 +0,0 @@
|
|||||||
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;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
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 static final GamePlay DEFAULT_PROFILE = new GamePlay();
|
|
||||||
public boolean isDefault = false;
|
|
||||||
|
|
||||||
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();
|
|
||||||
System.out.println("Unable to read from GamePlay file: " + fileName
|
|
||||||
+ ", initializing a new GamePlay instance.");
|
|
||||||
gp = GamePlay.DEFAULT_PROFILE;
|
|
||||||
gp.isDefault = true;
|
|
||||||
}
|
|
||||||
return gp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package dk.itu.mario.MarioInterface;
|
|
||||||
|
|
||||||
import dk.itu.mario.engine.DataRecorder;
|
|
||||||
|
|
||||||
public interface LevelGenerator {
|
|
||||||
public int generateLevelDifficulty (GamePlay playerMetrics, DataRecorder detailedInfo);
|
|
||||||
public int generateLevelType (GamePlay playerMetrics, DataRecorder detailedInfo);
|
|
||||||
public LevelInterface generateLevel (GamePlay playerMetrics);
|
|
||||||
public LevelInterface generateLevel (String detailedInfo);
|
|
||||||
public LevelInterface generateLevel (GamePlay playerMetrics, DataRecorder detailedInfo);
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
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
@@ -1,27 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,192 +0,0 @@
|
|||||||
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)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,212 +0,0 @@
|
|||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,342 +0,0 @@
|
|||||||
package dk.itu.mario.engine;
|
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.awt.Dimension;
|
|
||||||
import java.awt.Graphics;
|
|
||||||
import java.awt.GraphicsConfiguration;
|
|
||||||
import java.awt.Point;
|
|
||||||
import java.awt.Rectangle;
|
|
||||||
import java.awt.Robot;
|
|
||||||
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.BufferedImage;
|
|
||||||
import java.awt.image.VolatileImage;
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
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 boolean screenshotTaken = false;
|
|
||||||
private boolean useScale2x = false;
|
|
||||||
private boolean isCustom = false;
|
|
||||||
private int width, height;
|
|
||||||
private GraphicsConfiguration graphicsConfiguration;
|
|
||||||
private LevelGenerator levelGenerator;
|
|
||||||
private Scene scene;
|
|
||||||
private SonarSoundEngine sound;
|
|
||||||
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 (keyCode == KeyEvent.VK_D) {
|
|
||||||
if (!isPressed) {
|
|
||||||
screenshotTaken = false;
|
|
||||||
} else if (!screenshotTaken) {
|
|
||||||
screenshotTaken = true;
|
|
||||||
takeScreenShot();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isPressed && keyCode == KeyEvent.VK_ESCAPE) {
|
|
||||||
try {
|
|
||||||
System.exit(1);
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println("Unable to exit.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void takeScreenShot() {
|
|
||||||
System.out.println("Taking screenshot.");
|
|
||||||
Point loc = getLocationOnScreen();
|
|
||||||
|
|
||||||
Rectangle screenRect = new Rectangle(loc.x, loc.y, getWidth(), getHeight());
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
Robot robot = new Robot();
|
|
||||||
BufferedImage bufferedImg = robot.createScreenCapture(screenRect);
|
|
||||||
File tempFile = File.createTempFile("screenshot", ".png", new File("."));
|
|
||||||
ImageIO.write(bufferedImg, "png",
|
|
||||||
tempFile);
|
|
||||||
System.out.println("Screeshot saved to current working directory: " + tempFile.getName());
|
|
||||||
} catch (Exception ex) {
|
|
||||||
ex.printStackTrace(System.out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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() {
|
|
||||||
//while (true) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
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.PCGLevelGenerator;
|
|
||||||
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 = "PCGLevel";
|
|
||||||
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 ("PCGLevel".equals(generatorClass)) {
|
|
||||||
return new PCGLevelGenerator();
|
|
||||||
} 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,130 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
package dk.itu.mario.engine;
|
|
||||||
|
|
||||||
import com.thoughtworks.xstream.XStream;
|
|
||||||
import com.thoughtworks.xstream.io.xml.DomDriver;
|
|
||||||
|
|
||||||
public class XStreamFactory {
|
|
||||||
|
|
||||||
public static XStream getInstance() {
|
|
||||||
XStream xstream = new XStream(new DomDriver());
|
|
||||||
xstream.processAnnotations(DataRecorder.class);
|
|
||||||
|
|
||||||
return xstream;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BIN
src/dk/itu/mario/engine/sonar/.DS_Store
vendored
@@ -1,38 +0,0 @@
|
|||||||
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()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,145 +0,0 @@
|
|||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
package dk.itu.mario.engine.sonar;
|
|
||||||
|
|
||||||
|
|
||||||
public interface SoundListener extends SoundSource
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
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();
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
package dk.itu.mario.engine.sonar;
|
|
||||||
|
|
||||||
public interface SoundSource
|
|
||||||
{
|
|
||||||
public float getX(float alpha);
|
|
||||||
public float getY(float alpha);
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
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
@@ -1,93 +0,0 @@
|
|||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
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
@@ -1,114 +0,0 @@
|
|||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||