Category Archives: Random - Page 2

Have a better day!

(click for full image)

 

Yesterday I drew something. I tried to capture a very specific mood. It may or may not be iftpop related.

For the game itself there is nothing much to see, as I am currently switching the graphics framework (actually I am switching to *a* framework) and therefore everything is black – yay!

Have a better day!

Martin

Wall Jumps!

Did some work on the controller, which is getting feature complete more or less. It now allows for wall-runs and wall-jumping. Have a look at the new version and try to climb the two pillows.

Also, I added quite a bit of doxygen documentation to btKinematicCharacterController. For the interested I created a repository over at github (https://github.com/martinfelis/bulletphysics2) that contains the changes I made.

There are also improvements to the camera movement. There is no more jittering (thanks to the insights I gained about btKinematicCharacterController) and also the horizontal movement is no more constrained = much more fun!

Oh, and here is the new (windows) version: iftpop_0.0.2. Go Try It! NOW!

Additionally, I spilled some wine over my desktop keyboard.

IFTPOP 0.0.1 for Windows

All right! Windows version of the current code ready!

Grab it from here: iftpop-0.0.1

So far I am working on the controls for both camera and player movement. With the camera I am quite happy, but the player will get some more action features such as wall-jump and duck-slide, etc.

The camera starts to jitter at some point, but I do not yet know why.

Some informations about the game: it will feature some elements from racing games. And platformers. And nightmares.

Cheers,
Martin

New game: IFTPOP! first screenshot

Just a small screenshot of the current state of my next game, called “IFTPOP!” (what it actually means might be revealed at some point). The code so far is based upon my previous asteroids game but with a lot of new development. Biggest change so far: integration of bullet physics.

So long,
Martin

Scala + LWJGL + AWT = Resizable OpenGL Window

Following up on my previous post, I played around a bit more with Scala and LWJGL. What bothered me is that the standard examples for LWJGL and Scala had no resizable windows. But this is no more the case! It took me a bit to figure out how to translate various bloated Java examples to Scala but I am happy with the result.

Here is the code (btw.: does someone know how to make WP-Syntax a bit nicer looking?):

/**
 * Example program to get a resizable window using LWJGL + AWT in Scala.
 *
 * This code is public domain. Feel free to use it for anything you like.
 */
package org.fysx.lwjgltools
 
import java.awt._
import java.awt.event.{ComponentEvent, ComponentAdapter, WindowAdapter, WindowEvent}
import java.util.concurrent.atomic.{AtomicReference, AtomicBoolean}
 
import org.lwjgl._
import opengl.{Display,GL11,DisplayMode}
import GL11._
import input._
import math._
import org.lwjgl.opengl.AWTGLCanvas
 
class LWJGLFrame(text: String) extends Frame(text) {
  // tells us whether the screen was resized
  var resized = new AtomicBoolean()
  // the canvas on which the OpenGL context will be drawn
  var canvas = new Canvas()
  // this will store the new size after a resize
  var newCanvasSize = new AtomicReference[Dimension]
  // will be true if we received a window close request
  var closeRequested = false
  // used when resizing
  var newDim = new Dimension()
  // used for some animation
  var c = 0.0f
  var delta_c = 0.01f
 
  // added constructor in case we did not specify a String to LWJGLFrame()
  def this() {
    this("")
  }
 
  // add listener to the resize event
  canvas.addComponentListener (new ComponentAdapter() {
    override def componentResized(e: ComponentEvent) = {
//      println ("new size")
      newCanvasSize.set(canvas.getSize())
    }
  })
 
  // add the canvas our LWJGLFrame
  add(canvas, BorderLayout.CENTER)
 
  // add listener to the window close event
  addWindowListener(new WindowAdapter() {
    override def windowClosing (e: WindowEvent) = {
//      println ("close requested")
      closeRequested = true
    }
  })
 
  // adjust OpenGL context for change of the window size
  def resize() {
    newDim = newCanvasSize.getAndSet(null)
 
    if ( newDim != null ) {
//      println ("updating viewport")
      GL11.glViewport(0, 0, newDim.width, newDim.height)
    }
  }
 
  // perform the actual drawing
  def render() {
    c = c + delta_c
    if (c > 1.0f || c < 0.0f) delta_c = delta_c * -1.f
 
    GL11.glClearColor (0, 0, 0, 0)
    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT)
 
    glColor3f (1.0f, 1.0f, 1.0f)
    glBegin(GL_TRIANGLES)
    glColor3f (0.25f, 1-c, 0.25f)
    glVertex3f (-0.5f, -0.75f, 0.0f)
    glColor3f (0.5f, 0.25f, 1.0f-c)
    glVertex3f (0.5f, -0.75f, 0.0f)
    glColor3f (c, 0.5f, 0.25f)
    glVertex3f (0.f, 0.75f, 0.0f)
    glEnd
  }
 
  // handle keyboard and other events
  def logic() {
    import Keyboard._
 
    if (isKeyDown(KEY_I)) println ("Key I was pressed!")
  }
 
  // starts the OpenGL loop
  def run() {
//    println ("executing run()")
    try {
      // setup of the Display (connect it to the canvas)
      Display.setParent(canvas)
      try {
        Display.create()
      } catch {
        case e: LWJGLException => {
          e.printStackTrace()
          println (e.getMessage())
        }
      }
 
      Display.setVSyncEnabled(true)
 
      // the actual main loop
      while (!Display.isCloseRequested() && !closeRequested) {
        resize()
        Display.update()
 
        logic()
 
        render()
 
        Display.sync(60)
      }
 
      // we're done so we have to destroy the Display
      Display.destroy()
    }
  }
}
 
object Main {
  // actual entry point of the program
  def main(args: Array[String]) {
    var lwjglframe = new LWJGLFrame ("Scala + LWJGL + AWT = resizable window")
 
    lwjglframe.setMinimumSize(new Dimension(320, 240))
    lwjglframe.setSize(new Dimension(640, 480))
    lwjglframe.setVisible(true)
 
    lwjglframe.run()
 
    lwjglframe.dispose()
  }
}

Scala + LWJGL = Running Program

scala + lwjglI thought I would try to get the Lightweight Java Game Library (LWJGL) running in Scala as both are really hip nowadays. Turns out that there is not much available on teh internets that works. Most of them use the “Simple Build Tool” (sbt) which I did not find simple at all. Also they have a new version 0.10.x which is incompatible to the Scala+LWJGL examples which use sbt version 0.7.x. Yay!

Anyhow, I used the Scala code from http://lwjgl.org/forum/index.php?topic=3416.0 and finally managed to get it run without any “simple” tools or other dependencies. Here is how:

  1. Download the current LWJGL release (as of writing: 2.7.1). This should give you a zip file with a few jars, dlls and so files.
  2. Download and install Scala from http://www.scala-lang.org/ (as of writing: 2.9.1)
  3. Create the folders “lwjglproject/lib” and “lwjglproject/src”
  4. Extract all .jars to “lwjglproject/lib”. When using Windows do so with the dlls, on Linux put the .so files there and Mac users probably don’t have to do anything (that’s what I’m always being told)
  5. Create a source file “lwjglproject/src/lwjgl.scala” with contents from the example (also available further down)
  6. Compile the code with
    scalac -classpath ./lib/lwjgl.jar src/lwjgl.scala

    this should  give you some .class files

  7. Run the example by executing
    scala -classpath lib/lwjgl.jar -Djava.library.path=./lib Main
  8. Enjoy

Oh, and if you want to run the program directly with java to have to specify the path to scala-library.jar and add the (current) “lwjglproject” path to the classpath:

java -classpath .:lib/lwjgl.jar:/lib/scala-library.jar -Djava.library.path=./lib Main

Here is the code for the example:

import org.lwjgl._
import opengl.{Display,GL11,DisplayMode}
import GL11._
import input._
import math._
 
object Main{
	val GAME_TITLE = "My Game"
	val FRAMERATE = 60
	val width = 640
	val height = 480
 
	val player = new Player(0,0,0);
 
	var finished = false
	var angle = 0.0f
	var rotation = 0.0f
 
	def main(args:Array[String]){
		var fullscreen = false
		for(arg <- args){
			arg match{
				case "-fullscreen" =>
					fullscreen = true
			}
		}
 
		init(fullscreen)
		run
	}
 
	def init(fullscreen:Boolean){
 
		println("init Display")
		Display.setTitle(GAME_TITLE)
		Display.setFullscreen(fullscreen)
		Display.setVSyncEnabled(true)
		Display.setDisplayMode(new DisplayMode(width,height))
		Display.create
 
		println("init gl")
		glEnable(GL_DEPTH_TEST);
		glEnable(GL_LIGHTING)
		glEnable(GL_LIGHT0)
		adjustcam
	}
 
	def adjustcam(){
		val v = Display.getDisplayMode.getWidth.toFloat/Display.getDisplayMode.getHeight.toFloat
		printf("v:%f",v)
		glMatrixMode(GL_PROJECTION)
		glLoadIdentity
		glFrustum(-v,v,-1,1,1,100)
		glMatrixMode(GL_MODELVIEW)
	}
 
	def cleanup(){
		Display.destroy
	}
 
	def run(){
		while(!finished){
			Display.update
 
			logic
			render
 
			Display.sync(FRAMERATE)
		}
	}
 
	def logic(){
	    // in scala we can locally import all methods from Keyboard.
	    import Keyboard._
 
		if(isKeyDown(KEY_ESCAPE))
			finished = true
		if(Display.isCloseRequested)
			finished = true
 
		// rx and rx store our keyboard input as direction  
		var ry = 0
		var rx = 0
 
		// keys are IKJL for up down left right
 
		if(isKeyDown(KEY_I))
			ry += 1
		if(isKeyDown(KEY_K))
			ry -= 1
		if(isKeyDown(KEY_J))
			rx -= 1
		if(isKeyDown(KEY_L))
			rx += 1
 
		// this makes the direction relative to the camera position
		// it is a simple rotation matrix you may know from linear algebra
		val ax = rx*cos(-rotation.toRadians)-ry*sin(-rotation.toRadians)
		val ay = rx*sin(-rotation.toRadians)+ry*cos(-rotation.toRadians)
 
		player.x += 0.1f*ax.toFloat
		player.y += 0.1f*ay.toFloat
 
		// this rotates our camera around the center
		angle += 2.0f % 360
		rotation += 0.2f
	}
 
	def renderGrid(size : Int){
	    // this creates the nice looking background.
		glDisable(GL_LIGHTING)
		glBegin(GL_LINES)
		for(i <- -size to size){
			glVertex2i(i,-size)
			glVertex2i(i, size)
			glVertex2i(-size,i)
			glVertex2i( size,i)
		}
		glEnd
		glEnable(GL_LIGHTING)
	}
 
	def render(){
		glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		glLoadIdentity
 
		glTranslatef(0,0,-20)
		glRotatef(-70,1,0,0)
		glRotatef(rotation,0,0,1)
 
		glPushMatrix
		player.applyPos
		//rotate the player just for fun
		glRotatef(angle, 0, 0, 1.0f)
		player.draw
		glPopMatrix
 
		//without background, motion is not visible
		// a green grid is nice and retro
		glColor3f(0,1,0)
		renderGrid(10000)
	}
}
 
class Player(nx:Float,ny:Float,nz:Float){
	var x:Float = nx
	var y:Float = ny
	var z:Float = nz
 
	def applyPos {
	    glTranslatef(x,y,z)
	}
 
	def draw = {
		glColor3f(1, 0, 0)
		glBegin(GL_TRIANGLE_FAN)
		glNormal3d( 0, 0, 1);	glVertex3d(0,0,0.5)
		glNormal3d(-1,-1, 1);	glVertex2d(-0.5, -0.5)
		glNormal3d( 1,-1, 1);	glVertex2d(0.5, -0.5)
		glNormal3d( 1, 1, 1);	glVertex2d(0.5, 0.5)
		glNormal3d(-1, 1, 1);	glVertex2d(-0.5, 0.5)
		glNormal3d(-1,-1, 1);	glVertex2d(-0.5, -0.5)
		glEnd
	}
}

Asteroids finished!

Please note the “1.0.0″ at the top bar or at the bottom-left of the screen. Or just help yourself with one of these:

You may now call me a game developer.

Something more elaborate will follow, but for now I just have to enjoy the moment!

Online Highscores and Bonus Points

Bad news: Asteroids is not yet finished.

Good news: Asteroids will have lots of cool stuff in the final version!

Since my call for levels in my previous post I received a lot of uber awesome levels. I was really blasted away by the creativity of some contributions and it is very impressive to see what one can get out of such simple mechanics. It was very hard to order the levels into increasing difficulty while simultaneously trying keep the gameplay fresh and interesting. But you will get to see it soon enough…

Other than playing and sorting levels, I worked on two new features that I thought would be very interesting.

Online Highscore

When using the online highscore, the scores get submitted to the server and the top 10 scores from the server will me displayed in-game. This is all done by using SDL_net and performing some hand crafted HTTP queries to a small PHP script on the server. The PHP script itself stores the  highscore in a SQLite database which was super easy to set up.

As everything is transmitted in clear text I also added some protection to ensure only valid submissions are added to the database. I am using a shared secret for the PHP script and the game which gets appended to the submission values (name + score) and then hashed. As a hashing function I use Aaron D. Gifford’s sha256 code which should be sufficiently safe for this. What I really like about it is, that I could publish the code for both the script and the game but this would still be not enough to spam the highscore unless someone succeeds to extract the shared secret – Nice!

In the game options menu one can choose whether one wants to use this online highscore mode or only use the local highscore. The following screen shot should be pretty self explanatory:

Whether the online mode is being used or not can be seen by the highlighted “-online-” at the top of the highscore screen. In “-offline-” mode it uses the values stored in the game data path.

Bonus Points

Also there will be bonus points given when one finishes a level fast. For this I needed a time to compare to. Inspired by the PAR time in DOOM I played through all levels and added a few seconds. I am using a quadratic function to compute the amount of bonus points, depending on time and the number of asteroids in the level. Only when the level was finished before the PAR time. Currently I am tweaking the parameters of the function to properly reward the speeders.

I decided to give points at the end of the level so that one cannot achieve higher scores by playing a level with many asteroids multiple times by committing suicide on the last remaining asteroid and therefore getting twice as many points on the level.

Some Polishing

To make the level switching a little nicer, I am now displaying some informations about the level, such as the number, title, and the author of the current level:

Furthermore I worked on the credits screen and made new sounds by using sfxr (which is super awesome!). But I’ll write about all that another time…

Asteroids: Beta 2 + Level Editor + Level Making Contest (update)

All right! So here we have a new version including all fixes that people found playing the first beta. There were only few errors of which most my 12 and 15 year old cousins found (i.e. collisions were not reported when entities were warped from one side of the screen to another). On bigger glitch came from a assert statement that I added to OGLFT as there was a bug with the boundary boxes, but apart from that only little problems were found. Thanks for everyone playing the game!

Level Editor

I also made a level editor for them as my cousins really liked the game and wanted to make levels themselves. It took me only 2 days to create the editor such that they could start making levels on their own as I already built a small set of GUI widgets using my own IMGUI code. It felt really good writing it and didn’t expect it to be running that quick. It was very rewarding to look over their shoulders and see the fun they had creating levels.

Here are some screenshots of the editor in action:

Level Making Contest

As so many people had a lot of fun creating levels (and they seemed much more creative than I), I decided to give everyone the chance to create awesome levels that will be shipped with the final version.

To spice it a little bit up, I decided to have a small level making contest. The authors of the winning levels will be listed in the credits of the final version under the category “Level Designer” which will probably make you very a famous celebrity (at least among a handful of nerds).

All you have to do is send in levels via email to

m a r t i n @ f y s x . o r g

until February 20th 2011, 23:59 CET. I will then take a week of careful judgement and announce the winners by the end of February / beginning of March 2011. Please fill in the field “Author” when saving the levels with the name you would like to have listed in the credits.

Levels are saved as <levelname>.map in the directory of the game (windows) or in the current folder (linux). You only need to send these files to me. Multiple levels can be sent to me.

Download

You can get the new beta which also includes the level editor. The windows binaries can be downloaded from here:

And for those Ubuntu/Debian users you get nicely made packages (for both 32- and 64-bit systems) from here:

Update: new packages that also include menu entries and should work with older versions of Ubuntu:

Previous versions of the packages (no menu entries, linked against newer boost version 1.42):

They will also download all dependencies. However you should deinstall any previous versions. You need to run ´fysxasteroidseditor´ to start the editor. Make sure you find yourself in a writable directory as the editor will place temporary and saved maps into the current folder.

Blender vs. 3DMagix, 3DMagixPro, IllusionMage

I am a big fan of Blender, as it gives me the possibility to get work with a professional 3D modeling and animation tool without having to spend money on expensive commercial software. There sure are student versions of 3Dmax and such out there, but they only let you do educational stuff with them. If you intend to create a model or animation that you plan use in something commercial, you might violate their terms of use. In contrast to that, Blender gives me the freedom to do whatever I want with it.

Just recently some people started again to sell re-branded versions of Blender for money. This is perfectly legal, as free software gives you even the freedom to sell it. However those people do it in a way that they try to make money off work they didn’t do. I don’t like that. All the money that is given to them is way better spent by donating to the Blender Foundation, which will improve Blender eventually. I highly doubt that those people intend to support Blender…

Here is a link to the official report at the Blender site: 3DMagix, 3DMagixPro, IllusionMage, scam