view trunk/tests/ChipmunkDemos/gameApp.d @ 26:a77be3e27f39

fix macos version
author Stephan Dilly <stephan@extrawurst.org>
date Mon, 13 Dec 2010 15:32:42 +0100
parents f2287962b4b7
children b45f0b140d85
line wrap: on
line source


// written in the D programming language

/++
 +	Authors: Stephan Dilly, www.extrawurst.org
 +/

module gameApp;

import framework;

import drawSpace;

import chipmunkd.chipmunk;

import samples.LogoSmash;
import samples.Simple;
import samples.PyramidStack;
import samples.ChipmunkDemo;
import samples.Plink;
import samples.Tumble;
import samples.PyramidTopple;
import samples.Planet;
import samples.Query;
import samples.OneWay;
import samples.Sensors;
import samples.Bounce;
import samples.Springies;
import samples.Joints;
import samples.MagnetsElectric;
import samples.Player;
import samples.Tank;
import samples.Pump;
import samples.TheoJansen;
import samples.UnsafeOps;
import samples.Nukeit;

// using derelict bindings for sdl/opengl
import derelict.opengl.gl;
import derelict.opengl.glu;
import derelict.sdl.sdl;

import std.stdio;
import core.thread;

version = TIME_TRIAL;

cpVect			mousePos;
cpVect			arrowDirection;

bool key_up = false;
bool key_down = false;
bool key_left = false;
bool key_right = false;
bool key_space = false;

///
final class GameApp {

private:

	chipmunkDemo*[] demos;
	chipmunkDemo*	currentDemo;
	cpSpace*		space;
	int				ticks;
	cpBody*			mouseBody;
	cpConstraint*	mouseJoint;
	cpVect			mousePos_last;
	
	bool 	m_running = true;
	
	drawSpaceOptions options = {
		0,		// drawHash
		0,		// drawBB
		1,		// drawShapes
		4.0f,	// collisionPointSize
		0.0f,	// bodyPointSize
		1.5f,	// lineThickness
	};
	
	enum width = 1024;
	enum height = 780;
	
version(TIME_TRIAL)
{
	ulong time_trial(int index, int count)
	{
		currentDemo = demos[index];
		space = currentDemo.initFunc();
		
		auto start = .tickCount();
		
		foreach(i; 0..count)
			currentDemo.updateFunc(i);
		
		auto end = .tickCount();
		auto duration = (end - start);
		
		currentDemo.destroyFunc();
		currentDemo = null;
		
		writefln("Time(%s) = %s", cast(char)(index + 'a'), duration);
		
		return duration;
	}
}

	///
	public void boot() {

		demos = [
			&LogoSmash,
			//&Simple,
			&PyramidStack,
			&Plink,
			&Tumble,
			&PyramidTopple,
			&Bounce,
			&Planet,
			&Springies,
			&Pump,
			&TheoJansen,
			&MagnetsElectric,
			&UnsafeOps,
			&Query,
			&OneWay,
			&Player,
			&Sensors,
			&Joints,
			&Tank,
		];
			
		cpInitChipmunk();
		
		cp_collision_slop = 0.2f;
		
version(TIME_TRIAL)
{
		Thread.sleep(2_000_000);
		ulong duration;
		foreach(i; 0..demos.length)
		{
			if(i == 'l'-'a') continue;
			duration+=time_trial(i, 1000);
		}
	
		writefln("Time accum = %s", duration);
	
		m_running = false;
		
		return;
}//TIME_TRIAL
		
		//setup framework
		framework.startup("chipmunk'd by Stephan Dilly",width,height,false);

		reshape(width,height);
				
		glEnableClientState(GL_VERTEX_ARRAY);
		
		runDemo(&LogoSmash);
		
		mouseBody = cpBodyNew(INFINITY, INFINITY);
	}
		
	///
	void runDemo(chipmunkDemo *demo)
	{
		if(currentDemo)
			currentDemo.destroyFunc();
		
		currentDemo = demo;
		ticks = 0;
		mouseJoint = null;
		
		//maxArbiters = 0;
		//maxPoints = 0;
		//maxConstraints = 0;
		space = currentDemo.initFunc();
	}
					 
	///
	void reshape(int width, int height)
	{
		glViewport(0, 0, width, height);
		
		double rx = width / 2.0;
		double ry = height / 2.0;
		
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glOrtho(-rx, rx, -ry, ry, -1.0, 1.0);
		glTranslated(0.5, 0.5, 0.0);
	}

	///
	public bool update() {

		if(!m_running) return m_running;
		
		if(!framework.processEvents(&keyEvent,&mouseMove,&mouseButtonEvent))
			return false;
					 
		cpVect newPoint = cpvlerp(mousePos_last, mousePos, 0.25f);
		mouseBody.p = newPoint;
		mouseBody.v = cpvmult(cpvsub(newPoint, mousePos_last), 60.0f);
		mousePos_last = newPoint;
	
		currentDemo.updateFunc(ticks++);
		
		// render
		
		glClearColor(1,1,1,1);

		glClear(GL_COLOR_BUFFER_BIT);
		
		DrawSpace(space,currentDemo.drawOptions ? currentDemo.drawOptions : &options);

		SDL_GL_SwapBuffers();
					 
		return m_running;
	}

	///
	public void shutdown() {
		
version(TIME_TRIAL){}else
{
		currentDemo.destroyFunc();
					 
		framework.shutdown();
}
	}

	cpVect mouseToSpace(int x, int y)
	{
		GLdouble model[16];
		glGetDoublev(GL_MODELVIEW_MATRIX, model.ptr);
	
		GLdouble proj[16];
		glGetDoublev(GL_PROJECTION_MATRIX, proj.ptr);
	
		GLint view[4];
		glGetIntegerv(GL_VIEWPORT, view.ptr);
	
		GLdouble mx, my, mz;
		gluUnProject(x, height - y, 0.0f, model.ptr, proj.ptr, view.ptr, &mx, &my, &mz);
	
		return cpv(mx, my);
	}
	
	///
	private void mouseMove(int x,int y)
	{
		mousePos = mouseToSpace(x,y);
	}
	
	///
	private void mouseButtonEvent(int x,int y,bool _down)
	{	
		if(_down){
			cpVect point = mouseToSpace(x,y);
		
			cpShape *shape = cpSpacePointQueryFirst(space, point, GRABABLE_MASK_BIT, CP_NO_GROUP);
			if(shape){
				cpBody *_body = shape._body;
				mouseJoint = cpPivotJointNew2(mouseBody, _body, cpvzero, cpBodyWorld2Local(_body, point));
				mouseJoint.maxForce = 50000.0f;
				mouseJoint.biasCoef = 0.15f;
				cpSpaceAddConstraint(space, mouseJoint);
			}
		} else if(mouseJoint){
			cpSpaceRemoveConstraint(space, mouseJoint);
			cpConstraintFree(mouseJoint);
			mouseJoint = null;
		}
	}
	
	///
	private void set_arrowDirection()
	{
		int x = 0, y = 0;
	
		if(key_up) y += 1;
		if(key_down) y -= 1;
		if(key_right) x += 1;
		if(key_left) x -= 1;
	
		arrowDirection = cpv(x, y);
	}
	
	///
	private void keyEvent(int _key,bool _down)
	{				 
		int key = _key;
		
		if(_down)
		{
			int index = key - 'a';
			
			if(0 <= index && index < demos.length){
				runDemo(demos[index]);
			} else if(key == '\r'){
				runDemo(currentDemo);
			} else if(key == 47){
				options.drawHash = !options.drawHash;
			} else if(key == 92){
				options.drawBBs = !options.drawBBs;
			} else if(key == 27){
				m_running = false;
			} else if(key == 93){
				glEnable(GL_LINE_SMOOTH);
				glEnable(GL_POINT_SMOOTH);
				glEnable(GL_BLEND);
				glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
				glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
				glHint(GL_POINT_SMOOTH_HINT, GL_DONT_CARE);
			}
			else
			{
				if(key == SDLK_UP) key_up = true;
				else if(key == SDLK_DOWN) key_down = true;
				else if(key == SDLK_LEFT) key_left = true;
				else if(key == SDLK_RIGHT) key_right = true;
				else if(key == SDLK_SPACE) key_space = true;
	
				set_arrowDirection();
			}
		}
		else
		{
			if(key == SDLK_UP) key_up = false;
			else if(key == SDLK_DOWN) key_down = false;
			else if(key == SDLK_LEFT) key_left = false;
			else if(key == SDLK_RIGHT) key_right = false;
			else if(key == SDLK_SPACE) key_space = false;
			
			set_arrowDirection();
		}
	}
}