Game
Rottweiler4k is a game I wrote for Java 4k competition. As you may have guessed it is very small game packed to only 4092 bytes. To play right away press webstart / JAR / newest JAR.
2015 Edit: Please note that webstart doesn't work anymore.
Story
It is eat'em up game, with parallax scrolling. You are "Max" - big black rottweiller. Your mission is to eat 40 thieves trespassing your master's orchard. Use LEFT, RIGHT and UP arrows to move and jump. Press SPACE to clench jaws. When near the body press DOWN and SPACE to eat and heal. Remember to avoid deadly kicks.
Code
Since it was my first entry for Java4k I had to look for clues elswhere. My code was heavily influenced by Miners 4k. However I had some personal achievements. First is parallax scrolling a'la amiga's classic 'Shadow of The Beast'. Second one is the thieves animation. Those guys walk just like Another World's hero, and all their moves are hardcoded!
The final JAR was processed with ProGuard 3.7 and repacked with BJWFlate. Both are great tools. Here is the make.bat i used to build project:
del R.class
del R.jar
javac -g:none R.java
jar cvfM R.jar R.class
java -jar ..\java\proguard3.7\lib\proguard.jar @proguard.pro
unzip -o RR.jar
del R.jar
BJWFlate.exe -y -n -s2048 R.jar R.class
proguard.pro:
-injars R.jar
-outjars RR.jar
-libraryjars "C:/Program Files/Java/jdk1.5.0_10/jre/lib/rt.jar"
-printusage
-allowaccessmodification
-overloadaggressively
-keep public class R {
public static void main(java.lang.String[]);
}
And here is the main class file R.java:
/** Rottweiler 4k, by rostok(AT)3e.pl
*/
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.awt.geom.*;
import java.util.Random;
import javax.swing.*;
public class R extends JFrame
{
private static boolean[] keys = new boolean[65536];
// private static int mouseButton;
// private static int xMouse, yMouse;
/**
* This seems to be the smallest way of reading input events to the JFrame.
*/
public void processEvent(AWTEvent e)
{
switch (e.getID())
{
case WindowEvent.WINDOW_CLOSING:
System.exit(0);
// case MouseEvent.MOUSE_RELEASED:
// mouseButton = 0;
// break;
// case MouseEvent.MOUSE_PRESSED:
// mouseButton = ((MouseEvent)e).getButton();
// case MouseEvent.MOUSE_MOVED:
// case MouseEvent.MOUSE_DRAGGED:
// xMouse = ((MouseEvent)e).getX();
// yMouse = ((MouseEvent)e).getY();
break;
case KeyEvent.KEY_PRESSED:
case KeyEvent.KEY_RELEASED:
keys[((KeyEvent)e).getKeyCode()] = e.getID() == KeyEvent.KEY_PRESSED;
//System.out.println (((KeyEvent)e).getKeyCode());
}
}
public static void main(String[] args) throws Throwable
{
int screenW = 640;
int screenH = 448;
// var game vars
int maxJump = 150;
int horizon= 390;
// Create the window
R a = new R();
a.setSize(screenW, screenH);
a.setResizable(false);
a.enableEvents(KeyEvent.KEY_PRESSED | MouseEvent.MOUSE_DRAGGED | MouseEvent.MOUSE_MOVED | MouseEvent.MOUSE_PRESSED | MouseEvent.MOUSE_RELEASED);
a.setVisible(true);
// Set up the graphics objects we'll need
Graphics grScreen = a.getGraphics();
BufferedImage img = new BufferedImage(screenW, screenH, BufferedImage.TYPE_INT_RGB);
//int[] pixels = ((DataBufferInt)img.getRaster().getDataBuffer()).getData();
// backbuffer
BufferedImage imgBack = new BufferedImage(screenW, screenH, BufferedImage.TYPE_INT_RGB);
Graphics2D grBack = imgBack.createGraphics();
//grBack.setColor(new Color(255, 255, 255));
grBack.setRenderingHint ( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
// background
BufferedImage imgBgd = new BufferedImage(screenW, screenH, BufferedImage.TYPE_INT_RGB);
int[] pixelsBgd = ((DataBufferInt)imgBgd.getRaster().getDataBuffer()).getData();
Graphics2D grBgd = imgBgd.createGraphics();
// trees
BufferedImage imgTrees = new BufferedImage(2048, horizon, BufferedImage.TYPE_INT_ARGB);
int[] pixelsTrees = ((DataBufferInt)imgTrees.getRaster().getDataBuffer()).getData();
Graphics2D grTrees = imgTrees.createGraphics();
grTrees.setRenderingHint ( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
Random random = new Random();
// input
float dx = 0;
float dy = 0;
// temp
int i, j, k = 0, l = 0;
float d=0, aa, ta;
// ziemia
for (j=0; j<screenH; j++)
{
if (j<horizon)
{
for (i=0; i<screenW; i++)
pixelsBgd[i+j*screenW] =
( 81+ (255- 81) * j/horizon* j/horizon* j/horizon)<<16 |
(156+ (255-156) * j/horizon* j/horizon* j/horizon)<<8 |
255;
}
else
{
for (i=0; i<screenW; i++)
{
k = (j-horizon) * (random.nextInt(128)+128)>>8;
pixelsBgd[i+j*screenW] = 0x100010 | (random.nextInt(36)+100-100 * k/(screenH-horizon))<<8 ;
}
}
}
//drzewo
l=128;
int x0=l;
int y0=l+32;
// pien
for (j=y0+l>>1;j<horizon;j++)
for (i=x0-16;i<x0+16;i++)
{
// if (i >= 0 && j >= 0 && i < 2048 && j < horizon)
{
pixelsTrees[i+j*2048] = 0xff004000 | (random.nextInt(64)+64)<<16;
}
}
// liscie
// grTrees.setPaint( new Color(0xff208020) );
// grTrees.fill( new Ellipse2D.Float( x0-l, y0-l, l<<1, l<<1 ) );
grTrees.setStroke( new BasicStroke(8, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND) );
for (k=0; k<2000; k++)
{
i = random.nextInt(l*2)-l;
j = random.nextInt(l*2)-l;
if (i*i+j*j < (int)(l*l*0.9))
{
grTrees.setPaint( new Color(0xff200020 | (random.nextInt(64)+64)<<8 ) );
i+=x0;
j+=y0;
d = random.nextInt(1024)*0.012272f;
grTrees.drawLine(i,j,i+(int)(Math.sin(d)*d),j+(int)(Math.cos(d)*d)); // lisc
if (k>1950)
{
grTrees.setPaint( new Color(0xff30ff30) );
grTrees.fill( new Ellipse2D.Float( i+1, j-3, 6, 6 ) );
grTrees.fill( new Ellipse2D.Float( i-1, j, 10, 10 ) );
grTrees.setPaint( new Color(0xff30aa30) );
grTrees.fill( new Ellipse2D.Float( i+2, j-3, 6, 6 ) );
grTrees.fill( new Ellipse2D.Float( i, j, 10, 10 ) );
}
}
}
/**/
// kopiuj dalej
l+=l;
k=128;
for (i=0; i<16; i++)
{
k += random.nextInt(l)+l/2;
grTrees.drawImage(imgTrees,Math.min(2048-l,k),random.nextInt(32),Math.min(2048-l,k)+l,horizon,0,0,l,horizon,null);
}
while (!keys[27])
{
int globalX = 0;
boolean gameStarted=true;
int frame = 0;
// dog
int dogHealth=100;
int dogx=-200;
int dogy=horizon+5;
int dogDir=1;
int dogState = 0;
int dogJaws = 0;
float dogSpeedX= 0;
float dogSpeedY= 0;
int dogBite = 20;
int kills = 0;
// blood drops
float blood[][] = new float[2048][7];
// blood[][0] - x
// blood[][1] - y
// blood[][2] - old x
// blood[][3] - old y
// blood[][4] - speed x
// blood[][5] - speed y
// blood[][6] - state
// thiefs
int thiefKick = 10;
int thief[][] = new int[40][7];
// thief[][0] - x
// thief[][1] - y
// thief[][2] - health
// thief[][3] - state
// thief[][4] - attackstate
// thief[][5] - dir
// thief[][5] - rozkrok/speed
// thief setup
k=640;
for (i=0; i<40; i++)
{
k = thief[i][0] = k + random.nextInt(256)+128;
thief[i][1] = horizon+5;
thief[i][2] = 100;
thief[i][3] = 0;
thief[i][4] = 0;
// thief[i][3] = (i==0 ? 0 : -1);
thief[i][5] = -1;
// thief[i][6] = random.nextInt(40)+75;
}
// mouseButton = 0;
// main loop
while (gameStarted && !keys[27])
{
long fsTime=System.nanoTime();
frame++;
if (dogHealth>0)
{
// input
dx = 0;
dy = 0;
if (keys[37]) dx -= 10;
if (keys[39]) dx += 10;
if (keys[38]) dy -= 10;
if (keys[40]) dy += 10;
// dog logic
switch(dogState)
{
case 0: // stop
if (dx!=0) dogState=1; // run
if (dy>0 && dogHealth<100) dogState=5; // eat
break;
case 1: // run
if (dy>0) dogState=5; // eat
if (dy<0) dogState=2; // run
if (dy<0 && Math.abs(dogSpeedX)>0)
{
// jump start
dogSpeedY = -15;
dogState=2;
}
if (dy==0 && Math.abs(dogSpeedX)<1) dogState=0;
break;
case 2: // jump
dogSpeedY+=1;
if (dogy<horizon-maxJump || dy>=0 || dogSpeedY>0)
{
dogState=3; // fall
dogSpeedY=0;
}
break;
case 3: // fall
dy = 0;
dogSpeedY+=1;
if (dogy>=horizon+5)
{
// on ground
dogy=horizon+5;
dogSpeedY = 0;
if (dx!=0) dogState=1; // run
else dogState=0; // stop
}
break;
// case 4: // hit
// break;
case 5: // eat
if (dx!=0) dogState=1; // run
if (dogHealth==100) dogState=0; // stop
break;
// case 6: // dead
// break;
}
if (keys[32]) dogJaws = Math.min(100, dogJaws+20);
else dogJaws = Math.max(0, dogJaws-22);
//movement
dogSpeedX = Math.min(dogSpeedX + dx, 10)*0.9f;
dogSpeedX = Math.max(dogSpeedX ,-10);
if (dogSpeedX<0) dogDir = -1;
if (dogSpeedX>0) dogDir = 1;
dogx = Math.max(80, dogx+(int)dogSpeedX);
dogy = Math.min(horizon+5, dogy+(int)dogSpeedY);
if (dogx-globalX<80) { globalX = -dogx+80; }
if (dogx-globalX>320) { globalX = -dogx+320; }
}
// thief logic
for (i=0; i<40; i++)
{
switch (thief[i][3])
{
case 0: // pursuit
k = (dogHealth<=0) ? 1 : dogx - thief[i][0];
// k = dogx - thief[i][0];
if (k<0) thief[i][5] = 1;
if (k>0) thief[i][5] = -1;
if ( Math.abs(k) < screenW )
{
//if (k!=0)
thief[i][0] -= (random.nextInt(2)+1)*thief[i][5];//k/Math.abs(k);
// if (k!=0) thief[i][0] += (random.nextInt(2)+1)*k/Math.abs(k);
// if (k!=0) thief[i][0] += (thief[i][6]*k/100)/Math.abs(k);
}
// is dog close
if (Math.abs(dogx-thief[i][0])<50)
{
thief[i][3] = 1; // switch to attack
}
break;
case 1: // attack
if (Math.abs(dogx-thief[i][0])<50 && dogy>=horizon-maxJump>>1 && dogState!=6)
{
if (thief[i][4]>90) // front kick
{
dogHealth -= thiefKick;
dogx -= 3*thief[i][5];
if (dogHealth<=0)
{
dogState = 6;
dogSpeedY=0;
dogy = horizon;
}
if (thief[i][4]>100)
{
thief[i][3] = 2; // swing back
}
}
thief[i][4] += 20;
}
else
{
thief[i][3] = 2; // swing back
}
break;
case 2: // swing back
thief[i][4] -= 21;
if (thief[i][4]<=0)
{
thief[i][4]=0; // stop anim
thief[i][3]=0; // pursuit
}
break;
case 6: // dead
// if (Math.abs(thief[i][0]+40-dogx)<80)
// if (dogState==5)
// if (dogJaws>85)
// if (thief[i][2]>-100)
if (Math.abs(thief[i][0]+40-dogx)<80 && dogState==5 && dogJaws>85 && thief[i][2]>-100)
{
// System.out.println ("eat");
dogHealth = Math.min(dogHealth+dogBite/2+1, 100);
thief[i][2] -= dogBite;
if (thief[i][2]<=-100)
{
// eaten
thief[i][3] = -1;
}
// create blood drops
l = random.nextInt(32)+16;
k = 0;
j = 0;
while (j<l && k<2048)
{
if (blood[k][6]==0.0f)
{
blood[k][0] = dogx;
blood[k][1] = dogy-10;
blood[k][2] = dogx;
blood[k][3] = dogy-10;
blood[k][4] = (random.nextInt(500)-250)*0.01f;
blood[k][5] = -random.nextInt(500)*0.01f;
blood[k][6] = 1.0f;
j++;
//System.out.println ("blood drop"+j);
}
k++;
}
/* */
}
break;
}
// normal bite
if (thief[i][3] != 6)
if (thief[i][3] != -1)
if (Math.abs(thief[i][0]-dogx)<30)
if (keys[32] && dogJaws>50 && dogJaws<90) // closed
{
thief[i][2] -= dogBite; // reduce thief health
if (dogy < horizon)
{
thief[i][2] -= dogBite; // reduce thief health
}
// create blood drops
l = random.nextInt(32)+16;
k = 0;
j = 0;
while (j<l && k<2048)
{
if (blood[k][6]==0.0f)
{
blood[k][0] = dogx;
blood[k][1] = dogy-75;
blood[k][2] = dogx;
blood[k][3] = dogy-75;
blood[k][4] = dogSpeedX+(random.nextInt(1000)-500)*0.01f;
blood[k][5] = dogSpeedY-random.nextInt(500)*0.01f;
blood[k][6] = 1.0f;
j++;
//System.out.println ("blood drop"+j);
}
k++;
}
if (thief[i][2]<=0)
{
thief[i][4] = 0; // sotp anim
thief[i][3] = 6; // dead
thief[i][2] = 0;
kills++;
}
}
}
// blood logic
for (i=0; i<2048; i++)
if (blood[i][6]==1.0f)
{
if (blood[i][1]>=horizon) blood[i][6] = 0.0f;
blood[i][2] = blood[i][0];
blood[i][3] = blood[i][1];
blood[i][0]+= blood[i][4];
blood[i][1]+= blood[i][5];
blood[i][4]*=0.9;
blood[i][5]+=1;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// render screen ///////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// background
grBack.drawImage(imgBgd, 0, 0, null);
// grBack.drawImage(imgBgd, globalX % screenW, 0, null);
// grBack.drawImage(imgBgd, globalX % screenW+screenW, 0, null);
k=horizon;
l=horizon+4;
for (i=0; i<5; i++)
{
j = (globalX*(i+1)>>2) % screenW;
grBack.drawImage(imgBgd, j, k, j+screenW, l, 0,k, screenW, l, null);
grBack.drawImage(imgBgd, j+screenW, k, j+screenW+screenW, l, 0,k, screenW, l, null);
int oh2=l;
l+=(l-k)*(i+1);
k=oh2;
}
// trees
// grBack.drawImage(imgTrees, (globalX>>2) % 512, horizon*3/4, 512, horizon>>2, null);
// grBack.drawImage(imgTrees, (globalX>>2) % 512+512, horizon*3/4, 512, horizon>>2, null);
grBack.drawImage(imgTrees, (globalX>>1) % 1024, horizon>>1, 1024, 1+horizon>>1, null);
grBack.drawImage(imgTrees, (globalX>>1) % 1024+1024, horizon>>1, 1024, 1+horizon>>1, null);
grBack.drawImage(imgTrees, globalX % 2048, 3, null);
grBack.drawImage(imgTrees, globalX % 2048+2048, 3, null);
// thieves
for (i=0; i<40; i++)
{
if (thief[i][3]==-1) continue;
ta = -thief[i][4]*0.007854f;//0.01f*3.141592653589793f*0.25f;
int lx, ly, mx, my;
int llx, lly, mmx, mmy;
if (Math.abs(ta)>0.01f || thief[i][3]==6)
{ // kick
llx = -3+(int)(Math.sin(ta)*60);
lly = -63+(int)(Math.cos(ta)*60);
mx = mmx = -0;
my = -33;
mmy = -3;
lx = (-3+llx)>>1;
ly = (-63+lly)>>1;
k = (int)(Math.sin(ta/2.0f)*33);
l = -90+(int)(Math.cos(ta/2.0f)*33);
d = 0;
}
else
{ // walk
ta=(float)(((frame+i*3)%60)/30.0f*Math.PI);
d = (float)Math.cos(ta)/2.0f*0.9f; // rozkrok
// d = (float)Math.cos(ta)/2.0f*(thief[i][6]*0.01f); // rozkrok
lx = - 3+(int)(Math.sin(d)*30);
ly = -63+(int)(Math.cos(d)*30);
mx = -lx;
my = ly;
aa = (float)(Math.sin(ta+Math.PI)*Math.PI/5.0f+0.2f);
if (aa<0) aa=-aa/2;//
ta = (float)(Math.sin(ta )*Math.PI/5.0f+0.2f);
if (ta<0) ta=-ta/2;//
llx = lx+(int)(Math.sin(d+ta)*30);
lly = ly+(int)(Math.cos(d+ta)*30);
mmx = mx+(int)(Math.sin(-d+aa)*30);
mmy = my+(int)(Math.cos(-d+aa)*30);
k=(int)(Math.sin(d*1.2)*33);
l=-90+(int)(Math.cos(d*1.2)*33); // reka
}
d = -Math.max(mmy, lly)-5;
// if (frame<50 && i==1)
// System.out.println ((ta/Math.PI*180)+"\t"+(lx)+"\t"+(ly)+"\t"+(llx)+"\t"+(lly)+"");
// if (i==1)
// System.out.println ((mmy+d)+" "+(lly+d));
grBack.translate( globalX+thief[i][0], thief[i][1]+d );
grBack.scale( thief[i][5], 1 );
// dead
if (thief[i][3]==6) grBack.rotate(Math.PI/2.0f,-5,-15);
grBack.setPaint( new Color(0x8e6f6f) );
grBack.setStroke( new BasicStroke(7) );
grBack.drawLine( 0,-94, -3,-101); // kark
grBack.setPaint( Color.BLACK );
grBack.setStroke( new BasicStroke(15, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND) );
grBack.drawLine( -1,-109, -1,-113); // wlosy
grBack.setPaint( new Color(0xcd8e7e) );
grBack.setStroke( new BasicStroke(12, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND) );
grBack.drawLine( -3,-106, -3,-110); // glowa
// reka tylnia
grBack.setPaint( new Color(0xcd8e7e) );
grBack.setStroke( new BasicStroke(8, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND) );
grBack.drawLine(0,-85,-k,l); // reka
// nogi
grBack.setPaint( new Color(0x6f5f5f) );
grBack.setStroke( new BasicStroke(12, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND) );
grBack.drawLine(-3,-63,lx,ly); // noga
grBack.drawLine( 3,-63,lx,ly); // noga
grBack.drawLine(llx,lly,lx,ly); // noga
// grBack.setPaint( new Color(0xAAAAAA) );
// grBack.setStroke( new BasicStroke(6) );
// grBack.drawLine(llx,lly+3,llx-10,lly+3); // bucik
grBack.setPaint( new Color(0x8e6f6f) );
grBack.setStroke( new BasicStroke(12, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND) );
grBack.drawLine(-3,-63,mx,my); // noga
grBack.drawLine( 3,-63,mx,my); // noga
grBack.drawLine(mmx,mmy,mx,my); // noga
grBack.setPaint( new Color(0xAAAAAA) );
grBack.setStroke( new BasicStroke(6) );
grBack.drawLine(mmx,mmy+3,mmx-10,mmy+3); // bucik
grBack.drawLine(llx,lly+3,llx-10,lly+3); // bucik
// tulow
grBack.setPaint( new Color(0x202020) );
grBack.setStroke( new BasicStroke(16) );
grBack.drawLine( 0,-85,-2,-71);
grBack.drawLine( 0,-85, 2,-71);
// reka przednia
grBack.setPaint( new Color(0xcd8e7e) );
grBack.setStroke( new BasicStroke(8, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND) );
grBack.drawLine(0,-85,k,l);
// dead
if (thief[i][3]==6) grBack.rotate(-Math.PI/2,-5,-15);
grBack.scale( thief[i][5], 1 );
grBack.translate(-globalX-thief[i][0], -thief[i][1]-d );
}
// dog
d = (dogState==2 || dogState==3) ? (float)-Math.PI*0.4f : (float)Math.sin( (frame%20)/10.0f*Math.PI )*dogSpeedX/10.0f;
if (dogState==6) d=(float)(-Math.PI/2.0f); // dead
grBack.setPaint( Color.BLACK );
grBack.translate( globalX+dogx, k=(dogy + (dogState==6 ? 25:0)) );
grBack.scale( dogDir, 1 );
grBack.rotate(Math.PI*0.005125f*dogSpeedY,0,0); // jump rotate
grBack.setStroke( new BasicStroke(7) );
grBack.drawLine( -62,-24,-68+(int)(Math.sin(d)*20f),-24+(l=(int)(Math.cos(d)*20f))); // back leg
grBack.drawLine( -21,-22,-21-(int)(Math.sin(d)*20f),-22+l); // front leg
grBack.setStroke( new BasicStroke(18) );
grBack.drawLine( -57,-32,-24,-29 ); // stomach
grBack.drawLine( -54,-33,-25,-40 ); // upper body
if (dogState>=4) grBack.rotate(+1.09f,-21,-27);
grBack.drawLine( -22,-31,-15,-51 ); // neck
grBack.drawLine( -32,-34,-15,-51 ); // neck
grBack.setStroke( new BasicStroke(5) );
grBack.drawLine( -16,-47,- 6, (int)(-43.0f-dogJaws*0.04f) ); // lower jaw
grBack.setStroke( new BasicStroke(7) );
grBack.drawLine( - 9,-54,- 5,-54 ); // upper jaw
grBack.drawLine( -20,-57,-10,-57 ); // cap
// ucho
grBack.setPaint( new Color(0x202020) );
grBack.drawLine( -18,
-59,
-18-(int)(Math.sin(Math.abs(dogSpeedX)*0.05*Math.PI)*5.0f),
-59+(int)(Math.cos(Math.abs(dogSpeedX)*0.05*Math.PI)*5.0f) );
/**/
if (dogState>=4) grBack.rotate(-1.09f,-21,-27);
grBack.rotate(-Math.PI*0.005125f*dogSpeedY,0,0);
grBack.scale( dogDir, 1 );
grBack.translate( -globalX-dogx, -k);
// blood
grBack.setPaint( Color.RED );
grBack.setStroke( new BasicStroke(2) );
for (i=0; i<2048; i++)
if (blood[i][6]==1.0f)
{
grBack.drawLine( globalX+(int)blood[i][0], (int)blood[i][1],
globalX+(int)blood[i][2], (int)blood[i][3] );
}
grBack.setPaint( Color.WHITE );
grBack.drawString("Health:"+dogHealth, 10, 36);
grBack.drawString("Kills:"+kills, 10, 52);
if (kills>=40)
{
grBack.drawString("You won!", 310, 200);
}
if ((dogHealth<=0 && dogy==horizon) || (kills>=40))
{
grBack.drawString("Press ENTER to play!", 280, 240);
if (keys[10]) gameStarted=false;
}
/* grBack.drawString("dogy:"+dogy, 10, y); y+=16;
grBack.drawString("dogHealth:"+dogHealth, 10, y); y+=16;
grBack.drawString("dx:"+dx, 10, y); y+=16;
grBack.drawString("dy:"+dy, 10, y); y+=16;
grBack.drawString("dSx:"+dogSpeedX, 10, y); y+=16;
grBack.drawString("dSy:"+dogSpeedY, 10, y); y+=16;
grBack.drawString("globalX:"+globalX, 10, y); y+=16;
frameEndTime=System.nanoTime();
grBack.drawString("time:"+frame*1000000.0/(System.nanoTime()/1000-startTime/1000), 10, y); y+=16;
grBack.drawString("time:"+(1000000000.0f/(frameEndTime-frameStartTime)), 10, y); y+=16;
frameStartTime=System.nanoTime();
*/
// show frame
grScreen.drawImage(imgBack, 0, 0, null);
// A small sleep prevents the game from eating all the cpu power
// Thread.sleep(10);
fsTime = (System.nanoTime()-fsTime)/1000000;
if (fsTime<20)
Thread.sleep(20-fsTime);
}
}
// System.exit(0) makes sure nothing is left in the background
System.exit(0);
}
}
Review from http://x2d.org/java/4k/2007/
Rottweiler4k (Rostok)
|
|
Where to begin? I really don't know what to say about this game. On one level, it's very pretty, nicely animated, and well exectued. It's also a grotesque killing game with rather repetitive gameplay. All in all, I think it's a decent game, but it's confusing nonetheless.
|
Excellent graphics, good gameplay, technically decent.
Graphics 4
Gameplay 2
Technical 2
Other Nothing in particular
Total score 8
|
review from http://www.java-gaming.org/index.php?topic=16378.30
In Rottweiler 4k, the player controls a (big) black rottweiler on his mission to kill all the thieves in the pear orchard. Game controls are left-right, up to jump, space to clench jaws, and down and space to eat killed thieves (and restore ... energy or something).
Category:
Graphics: 4 it's amazing what one can do with all those simple geometric shapes
Technical: 2 seems a little more complicated than just simple collision detection
Gameplay: 1 repetitive
Other: 1 animated characters (dog,thieves)
1 parallax scrolling
-1 see remarks
Total: 8
Problems:
The top of the screen is cut off under linux (i.e. you can't see the health and the number of kills).
Remark:
Considering that this game only uses simple geometric shapes, the graphics are exceptionally well done. The one big downside is that thieves kicks can hit the dog even if he is in the air above their heads. Wtf?
..