# HG changeset patch # User fred@reichbier.de # Date 1216390361 -7200 # Node ID 292df259cc859eab104249a6de33fbc9f16c8b05 # Parent a9af6ec19195f298d15e660100f06ec8eee6b45c view + sprite consumers, animated sprite working diff -r a9af6ec19195 -r 292df259cc85 bin/map-example.xml --- 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 @@ - + - 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 diff -r a9af6ec19195 -r 292df259cc85 src/animatedsprite.d --- /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; + } + } + } +} diff -r a9af6ec19195 -r 292df259cc85 src/consumer.d --- 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); + } } diff -r a9af6ec19195 -r 292df259cc85 src/renderer.d --- 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 diff -r a9af6ec19195 -r 292df259cc85 src/sprite.d --- /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; diff -r a9af6ec19195 -r 292df259cc85 src/spriteconsumer.d --- /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); + } + } +} + diff -r a9af6ec19195 -r 292df259cc85 src/test.d --- 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; diff -r a9af6ec19195 -r 292df259cc85 src/tileconsumer.d --- 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); } } } diff -r a9af6ec19195 -r 292df259cc85 src/tilemap.d --- 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) { diff -r a9af6ec19195 -r 292df259cc85 src/viewconsumer.d --- /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; + } +}