changeset 4:292df259cc85

view + sprite consumers, animated sprite working
author fred@reichbier.de
date Fri, 18 Jul 2008 16:12:41 +0200
parents a9af6ec19195
children f4b89014ad39
files bin/map-example.xml src/animatedsprite.d src/consumer.d src/renderer.d src/sprite.d src/spriteconsumer.d src/test.d src/tileconsumer.d src/tilemap.d src/viewconsumer.d
diffstat 10 files changed, 234 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/bin/map-example.xml	Thu Jul 17 21:34:53 2008 +0200
+++ b/bin/map-example.xml	Fri Jul 18 16:12:41 2008 +0200
@@ -1,7 +1,7 @@
-<map version="1" width="3" height="3">
+<map version="1" width="36" height="10">
   <tiles tileset="tileset-example.xml">
     <layer tilewidth="32" tileheight="32">
-      1,1,1,0,0,0,1,1,1
+      1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1
     </layer>
   </tiles>
 </map>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/animatedsprite.d	Fri Jul 18 16:12:41 2008 +0200
@@ -0,0 +1,76 @@
+module animatedsprite;
+
+import dsfml.window.all;
+import dsfml.system.all;
+import dsfml.graphics.all;
+
+class Frame {
+    Image image;
+    int length; // length in frames
+
+    this(Image image, int length) {
+	this.image = image;
+	this.length = length;
+    }	
+}
+
+class Animation {
+    private Frame[] frames;
+    private int current_frame_idx;
+    private Frame current_frame;
+    private int frame_counter;
+
+    this() {
+    
+    }
+
+    void add_frame(Image image, int length) {
+	this.frames ~= new Frame(image, length);
+    }
+
+    void play() {
+	this.current_frame = this.frames[0];
+	this.current_frame_idx = 0;
+    }
+
+    Image get_image() {
+	if(this.frame_counter >= this.current_frame.length) {
+	    this.frame_counter = 0;
+	    this.current_frame_idx++;
+	    if (this.frames.length <= this.current_frame_idx) {
+		// animation stop
+		return null;
+	    }
+	    this.current_frame = this.frames[this.current_frame_idx];
+	}
+	this.frame_counter++;
+	return this.current_frame.image;
+    }
+}
+
+class AnimatedSprite : Sprite {
+    private Animation current_animation = null;
+    private bool is_loop = false;
+
+    /* play an animation now. */
+    void play_animation(Animation animation, bool loop=false) {
+	this.current_animation = animation; 
+	this.is_loop = loop;
+	this.current_animation.play();
+    }
+
+    /* update everything. Perfect for an animated sprite */
+    void update() {
+	if(this.current_animation) {
+	    Image img = this.current_animation.get_image();
+	    if(img) {
+		this.setImage(img);
+	    }
+	    else if (this.is_loop) {
+		this.current_animation.play(); // is a loop, play again
+	    } else {
+		this.current_animation = null;
+	    }
+	}	    
+    }	
+}
--- a/src/consumer.d	Thu Jul 17 21:34:53 2008 +0200
+++ b/src/consumer.d	Fri Jul 18 16:12:41 2008 +0200
@@ -7,14 +7,20 @@
 import renderer;
 
 class Consumer {
-    protected RenderWindow app;
+    protected Renderer renderer;
 
     this(Renderer renderer) {
-	this.app = renderer.app;
+	this.renderer = renderer;
     }
 
+    /* handle the event `evt`. Return true if the event was handled and should not
+       be propagated any further, otherwise false */
+    bool handle_event(Event evt) {
+	return false;
+    }
+
+    /* draw all the content of this with this.app.draw(stuff) */
     void draw() {
-	Shape shape = Shape.circle(300, 300, 100, Color.WHITE);
-	this.app.draw(shape);
+
     }
 }
--- a/src/renderer.d	Thu Jul 17 21:34:53 2008 +0200
+++ b/src/renderer.d	Fri Jul 18 16:12:41 2008 +0200
@@ -6,11 +6,13 @@
 
 import consumer;
 import imagecache;
+import animatedsprite;
 
 class Renderer {
     public RenderWindow app;
     public Cache cache;
-    private Consumer[] consumers;
+    private Consumer[] draw_consumers;
+    private Consumer[] event_consumers;
     
     this(char[] title, int width, int height, int depth=32) {
 	this.app = new RenderWindow(VideoMode(width, height, depth), title);
@@ -19,8 +21,39 @@
 	this.cache = new Cache("."); // TODO
     }
 
+    /* add a consumer for event handling and drawing */
     void add_consumer(Consumer consumer) {
-	this.consumers ~= consumer;
+	this.add_event_consumer(consumer);
+	this.add_draw_consumer(consumer);
+    }
+
+    /* add a consumer only for event handling */
+    void add_event_consumer(Consumer consumer) {
+	this.event_consumers ~= consumer;
+    }
+
+    /* add a consumer only for drawing */
+    void add_draw_consumer(Consumer consumer) {
+	this.draw_consumers ~= consumer;
+    }
+
+    /* use this instead of this.app.draw - it contains a hook for animated sprites */
+    void draw(AnimatedSprite obj) {
+	obj.update();
+	this.app.draw(obj);
+    }
+
+    void draw(IDrawable obj) {
+	this.app.draw(obj);
+    }
+
+    void draw(Sprite obj) {
+	if(cast(AnimatedSprite)obj !is null) {
+	    this.draw(cast(AnimatedSprite)obj);
+	}
+	else {
+	    this.app.draw(obj);
+	}
     }
 
     /* start the mainloop */
@@ -32,10 +65,14 @@
 	    while(this.app.getEvent(evt)) {
 		if (evt.Type == Event.EventType.CLOSED) {
 		    this.app.close();
+		} else {
+		    foreach(Consumer consumer; this.event_consumers) {
+			if(consumer.handle_event(evt)) break;
+		    }
 		}		    
 	    }
 	    // draw all
-	    foreach(Consumer consumer; this.consumers) {
+	    foreach(Consumer consumer; this.draw_consumers) {
 		consumer.draw();
 	    }
 	    // display all
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sprite.d	Fri Jul 18 16:12:41 2008 +0200
@@ -0,0 +1,7 @@
+module sprite;
+
+import dsfml.window.all;
+import dsfml.system.all;
+import dsfml.graphics.all : Sprite = SFSprite;
+
+import renderer;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/spriteconsumer.d	Fri Jul 18 16:12:41 2008 +0200
@@ -0,0 +1,28 @@
+module spriteconsumer;
+
+import dsfml.window.all;
+import dsfml.system.all;
+import dsfml.graphics.all;
+
+import animatedsprite;
+import consumer;
+import renderer;
+
+class SpriteConsumer : Consumer {
+    private Sprite[] sprites;
+
+    this(Renderer renderer) {
+	super(renderer);
+    }
+
+    void add_sprite(Sprite sprite) {
+	this.sprites ~= sprite;
+    }
+
+    void draw() {
+	 foreach(Sprite sprite; this.sprites) { 
+	    this.renderer.draw(sprite);
+	 }
+    }
+}
+
--- a/src/test.d	Thu Jul 17 21:34:53 2008 +0200
+++ b/src/test.d	Fri Jul 18 16:12:41 2008 +0200
@@ -12,13 +12,28 @@
 import tileset;
 import xmlmap;
 import tools;
+import viewconsumer;
+import animatedsprite;
+import spriteconsumer;
 
 int main(char[][] args) {
     Cache cache = new Cache("gfx");
     Tilemap map = parse_map(cache, read_file_contents("map-example.xml"));
     Renderer render = new Renderer("Blubb", 600, 480, 32);
-    TileConsumer consumer = new TileConsumer(render, map);
-    render.add_consumer(consumer);
+//    render.add_consumer(new InteractiveViewConsumer(render));
+//    TileConsumer consumer = new TileConsumer(render, map);
+//    render.add_consumer(consumer);
+    SpriteConsumer c = new SpriteConsumer(render);
+    AnimatedSprite s = new AnimatedSprite;
+    s.setX(10);
+    s.setY(10);
+    Animation a = new Animation;
+    a.add_frame(map.tileset.tiles[0], 10);
+    a.add_frame(map.tileset.tiles[1], 10);
+//    s.setImage(map.tileset.tiles[0]);
+    s.play_animation(a, true);
+    c.add_sprite(s);
+    render.add_consumer(c);
 
     render.mainloop();
     return 0; 
--- a/src/tileconsumer.d	Thu Jul 17 21:34:53 2008 +0200
+++ b/src/tileconsumer.d	Fri Jul 18 16:12:41 2008 +0200
@@ -19,7 +19,7 @@
 
     void draw() {
 	 foreach(Sprite sprite; this.map.get_sprites()) {
-	    this.app.draw(sprite);
+	    this.renderer.draw(sprite);
 	 }
     }
 }
--- a/src/tilemap.d	Thu Jul 17 21:34:53 2008 +0200
+++ b/src/tilemap.d	Fri Jul 18 16:12:41 2008 +0200
@@ -13,7 +13,7 @@
 class Tilemap {
     public int[int][int][int] map; // Layer: x: y: Tile-ID
     public Vector2i[int] layer_tsizes; // Layer: Tile size
-    private Tileset tileset;
+    public Tileset tileset;
     public int width, height, tilewidth, tileheight;
 
     this(Tileset tileset, int width, int height, int tilewidth, int tileheight) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/viewconsumer.d	Fri Jul 18 16:12:41 2008 +0200
@@ -0,0 +1,52 @@
+module viewconsumer;
+
+import dsfml.window.all;
+import dsfml.system.all;
+import dsfml.graphics.all;
+
+import consumer;
+import renderer;
+import tango.io.Stdout;
+
+/* That is a consumer which sets and manipulates the render window view */
+class ViewConsumer : Consumer {
+    protected View view;
+
+    this(Renderer renderer) {
+	super(renderer);
+	// set the initial view
+	this.view = renderer.app.getView();
+	this.view.setFromRect(new FloatRect(0, 0, renderer.app.getWidth(), renderer.app.getHeight()));
+	this.update_view();
+    }
+
+    protected void update_view() {
+	this.renderer.app.setView(this.view);
+    }
+
+    void move_view(float x=0, float y=0) {
+	this.view.move(x, y);
+    }
+}
+
+class InteractiveViewConsumer : ViewConsumer {
+    this(Renderer renderer) {
+	super(renderer);
+    }
+
+    bool handle_event(Event evt) {
+	if (evt.Type == Event.EventType.KEYPRESSED) {
+	    float x=0, y=0;
+	    if(evt.Key.Code == KeyCode.LEFT) x -= 2;
+	    if(evt.Key.Code == KeyCode.RIGHT) x += 2;
+	    if(evt.Key.Code == KeyCode.UP) y -= 2;
+	    if(evt.Key.Code == KeyCode.DOWN) y += 2;
+	    if(x != 0 || y != 0) {
+		Stdout.formatln("{} fps", 1.0 / this.renderer.app.getFrameTime());
+		this.move_view(x, y);
+		return true;
+	    }
+	}
+	return false;
+    }
+}