1 /*
2 Copyright (c) 2015 Timur Gafarov
3 
4 Boost Software License - Version 1.0 - August 17th, 2003
5 
6 Permission is hereby granted, free of charge, to any person or organization
7 obtaining a copy of the software and accompanying documentation covered by
8 this license (the "Software") to use, reproduce, display, distribute,
9 execute, and transmit the Software, and to prepare derivative works of the
10 Software, and to permit third-parties to whom the Software is furnished to
11 do so, all subject to the following:
12 
13 The copyright notices in the Software and this entire statement, including
14 the above license grant, this restriction and the following disclaimer,
15 must be included in all copies of the Software, in whole or in part, and
16 all derivative works of the Software, unless such copies or derivative
17 works are solely in the form of machine-executable object code generated by
18 a source language processor.
19 
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
23 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
24 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
25 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 DEALINGS IN THE SOFTWARE.
27 */
28 
29 module dgl.graphics.sprite;
30 
31 import derelict.opengl.gl;
32 import dlib.core.memory;
33 import dlib.image.color;
34 import dlib.math.vector;
35 import dgl.core.event;
36 import dgl.core.interfaces;
37 import dgl.graphics.texture;
38 import dgl.graphics.material;
39 
40 // TODO: make all these children of one Sprite class
41 
42 class ScreenSprite: EventListener, Drawable
43 {
44     Material material;
45 
46     this(EventManager em, Texture tex)
47     {
48         super(em);
49         material = New!Material();
50         material.shadeless = true;
51         material.textures[0] = tex;
52     }
53 
54     override void draw(double dt)
55     {
56         material.bind(dt);
57         glBegin(GL_QUADS);
58         glTexCoord2f(0, 0); glVertex2f(0, eventManager.windowHeight);
59         glTexCoord2f(0, 1); glVertex2f(0, 0);
60         glTexCoord2f(1, 1); glVertex2f(eventManager.windowWidth, 0);
61         glTexCoord2f(1, 0); glVertex2f(eventManager.windowWidth, eventManager.windowHeight);
62         glEnd();
63         material.unbind();
64         glDisable(GL_LIGHTING);
65     }
66 
67     override void free()
68     {
69         Delete(this);
70     }
71 
72     ~this()
73     {
74         material.free();
75     }
76 }
77 
78 class Sprite: Drawable
79 {
80     Texture texture;
81     uint width;
82     uint height;
83     Vector2f position;
84 
85     this(Texture tex, uint w, uint h)
86     {
87         texture = tex;
88         width = w;
89         height = h;
90         position = Vector2f(0, 0);
91     }
92 
93     void draw(double dt)
94     {
95         glDisable(GL_DEPTH_TEST);
96         glPushMatrix();
97         glColor4f(1,1,1,1);
98         glTranslatef(position.x, position.y, 0.0f);
99         glScalef(width, height, 1.0f);
100         texture.bind(dt);
101         glBegin(GL_QUADS);
102         glTexCoord2f(0, 0); glVertex2f(0, 1);
103         glTexCoord2f(0, 1); glVertex2f(0, 0);
104         glTexCoord2f(1, 1); glVertex2f(1, 0);
105         glTexCoord2f(1, 0); glVertex2f(1, 1);
106         glEnd();
107         texture.unbind();
108         glPopMatrix();
109         glEnable(GL_DEPTH_TEST);
110     }
111 
112     ~this()
113     {
114     }
115 
116     void free()
117     {
118         Delete(this);
119     }
120 }
121 
122 class AnimatedSprite: Drawable
123 {
124     Texture texture;
125     uint tileWidth;
126     uint tileHeight;
127     uint tx = 0;
128     uint ty = 0;
129     uint numHTiles;
130     uint numVTiles;
131     float framerate = 1.0f / 25.0f;
132     double counter = 0.0;
133     Vector2f position;
134 
135     this(Texture sheetTex, uint w, uint h)
136     {
137         texture = sheetTex;
138         tileWidth = w;
139         tileHeight = h;
140         numHTiles = texture.width / tileWidth;
141         numVTiles = texture.height / tileHeight;
142         position = Vector2f(0, 0);
143     }
144 
145     void draw(double dt)
146     {
147         counter += dt;
148         if (counter >= framerate)
149         {
150             counter = 0.0;
151             advanceFrame();
152         }
153 
154         float u = cast(float)(tx * tileWidth) / texture.width;
155         float v = cast(float)(ty * tileHeight) / texture.height;
156         float w = cast(float)tileWidth / texture.width;
157         float h = cast(float)tileHeight / texture.height;
158 
159         glDisable(GL_DEPTH_TEST);
160         glPushMatrix();
161         glColor4f(1,1,1,1);
162         glTranslatef(position.x, position.y, 0.0f);
163         glScalef(tileWidth, tileHeight, 1.0f);
164         texture.bind(dt);
165         glBegin(GL_QUADS);
166         glTexCoord2f(u, v + h);     glVertex2f(0, 0);
167         glTexCoord2f(u + w, v + h); glVertex2f(1, 0);
168         glTexCoord2f(u + w, v);     glVertex2f(1, 1);
169         glTexCoord2f(u, v);         glVertex2f(0, 1);
170         glEnd();
171         texture.unbind();
172         glPopMatrix();
173         glEnable(GL_DEPTH_TEST);
174     }
175 
176     void advanceFrame()
177     {
178         tx++;
179         if (tx >= numHTiles)
180         {
181             tx = 0;
182             ty++;
183 
184             if (ty >= numVTiles)
185             {
186                 ty = 0;
187             }
188         }
189     }
190 
191     ~this()
192     {
193     }
194 
195     void free()
196     {
197         Delete(this);
198     }
199 }