http://tdr.dy.fi/lammaspeli_win32.zipTuossa on windowsille exet ja tarvittavat dll:t, sekä myös lähdekoodi.
// g++ lammaspeli.cpp -o lammaspeli.exe -lmingw32 -mwindows -lSDLmain -lSDL -lopengl32 -lglu32 -lSDL_image
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <SDL/SDL_opengl.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <iostream>
#include <string>
#include <sstream>
#define FONT_WIDTH 16
#define FONT_HEIGHT 16
// This is a nice little structure for your texture information
struct texture
{
GLuint number;
int width;
int height;
};
texture font;
// This function checks if OpenGL is OK. If it's not then the error is printed and program aborted.
void CheckGL()
{
GLenum errflag;
bool no_errors = true;
while ((errflag = glGetError()) != GL_NO_ERROR)
{
no_errors = false;
std::cerr << "GL error: " << gluErrorString(errflag) << "\n";
}
if (!no_errors)
abort();
}
texture LoadTexture(std::string texture_filename)
{
std::cerr << "Loading \"" << texture_filename << "\"\n";
texture t;
t.number = t.width = t.height = 0;
SDL_Surface* temp = IMG_Load(texture_filename.c_str());
if (temp == NULL)
{
std::cerr << IMG_GetError() << "\n";
return t;
}
// Check that the image's width is a power of 2
if ( (temp->w & (temp->w - 1)) != 0 )
std::cerr << "warning: width is not a power of 2\n";
if ( (temp->h & (temp->h - 1)) != 0 )
std::cerr << "warning: height is not a power of 2\n";
GLenum texture_format;
// get the number of channels in the SDL surface
int nOfColors = temp->format->BytesPerPixel;
if (nOfColors == 4) // contains an alpha channel
{
if (temp->format->Rmask == 0x000000ff)
texture_format = GL_RGBA;
else
texture_format = GL_BGRA;
}
else if (nOfColors == 3) // no alpha channel
{
if (temp->format->Rmask == 0x000000ff)
texture_format = GL_RGB;
else
texture_format = GL_BGR;
}
else
{
std::cerr << "warning: the image is not truecolor.. this will probably break\n";
// this error should not go unhandled
}
t.width = temp->w;
t.height = temp->h;
glGenTextures( 1, &t.number ); // Tell OpenGL to generate space from your video card for your texture
CheckGL();
glBindTexture( GL_TEXTURE_2D, t.number ); // Tell OpenGL which texture we are working on
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Textures rendering properties, check OpenGL manual
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // same
if (SDL_MUSTLOCK(temp)) // Tests if SDL requires the temp surface to be locked before we can access the pixel data
SDL_LockSurface(temp);
// This is the "big opengl texture loading function". It's somewhat complicated, the idea is to tell OpenGL from where and how to load all the pixels for the texture
glTexImage2D( GL_TEXTURE_2D, 0, temp->format->BytesPerPixel, t.width, t.height, 0, texture_format, GL_UNSIGNED_BYTE, temp->pixels );
if (SDL_MUSTLOCK(temp))
SDL_UnlockSurface(temp);
/* cleanup */
SDL_FreeSurface( temp );
CheckGL();
return t;
}
void FreeTexture(texture t)
{
if (glIsTexture(t.number) == GL_TRUE)
glDeleteTextures(1, &t.number);
}
void DrawBackground(texture t, int bgsize_x, int bgsize_y)
{
glBindTexture(GL_TEXTURE_2D, t.number);
glBegin( GL_QUADS );
glTexCoord2i(0, 0);
glVertex2i(0, 0);
glTexCoord2i(1, 0);
glVertex2i(bgsize_x, 0);
glTexCoord2i(1, 1);
glVertex2i(bgsize_x, bgsize_y);
glTexCoord2i(0, 1);
glVertex2i(0, bgsize_y);
glEnd();
}
void DrawTexture(texture t, int x, int y)
{
glBindTexture(GL_TEXTURE_2D, t.number);
glBegin( GL_QUADS );
glTexCoord2i(0, 0);
glVertex2i(x, y);
glTexCoord2i(1, 0);
glVertex2i(x + t.width, y);
glTexCoord2i(1, 1);
glVertex2i(x + t.width, y + t.height);
glTexCoord2i(0, 1);
glVertex2i(x, y + t.height);
glEnd();
}
void WriteText(std::string text, int x, int y)
{
glBindTexture(GL_TEXTURE_2D, font.number);
glBegin( GL_QUADS );
char c;
int cx, cy;
float fcx, fcy;
int i = 0;
while (i < text.length())
{
c = text.at(i);
cx = c % 16;
cy = c / 16;
fcx = float (cx) / 16.0f;
fcy = float (cy) / 16.0f;
glTexCoord2f(fcx, fcy);
glVertex2i(x + i * FONT_WIDTH , y);
glTexCoord2f(fcx + 1.0f / 16.0f, fcy);
glVertex2i(x + i * FONT_WIDTH + FONT_WIDTH , y);
glTexCoord2f(fcx + 1.0f / 16.0f, fcy + 1.0f / 16.0f);
glVertex2i(x + i * FONT_WIDTH + FONT_WIDTH , y + FONT_HEIGHT);
glTexCoord2f(fcx, fcy + 1.0f / 16.0f);
glVertex2i(x + i * FONT_WIDTH , y + FONT_HEIGHT);
i++;
}
glEnd();
}
int main(int argc, char** argv)
{
int retval = SDL_Init(SDL_INIT_VIDEO);
if (retval)
{
std::cerr << "SDL_Init() failed\n";
return retval;
}
SDL_Surface* screen = SDL_SetVideoMode(1280, 720, 32, SDL_OPENGL);
if (screen == NULL)
{
std::cerr << "SDL_SetVideoMode() failed\n";
return -1;
}
SDL_WM_SetCaption("Lammaspeli", NULL);
// Tells OpenGL what portion of the screen it can draw to, this time we use the whole screen SDL made for us
glViewport(0, 0, screen->w, screen->h);
glMatrixMode(GL_PROJECTION); // Tell OpenGL we are now modifying the projection aspects which means roughly how wide your viewing angle is
glLoadIdentity(); // Erase all the shit from the projection stack
gluOrtho2D(0, screen->w, screen->h, 0); // This tells OpenGL about the aspects of the view, check for OpenGL manual for better explanation of what this does
// Various cool settings OpenGL can do
glMatrixMode(GL_MODELVIEW); // now we are modifying the model stack which is where we draw everything
glLoadIdentity(); // erase all shit
glDisable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D); // Tell OpenGL we are drawing textured polygons (polygons means different shapes like triangles, quads, lines, circles etc.)
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // The background color
glColor3f(1.0f, 1.0f, 1.0f); // The primary drawing color (for example if you don't want to draw textured polygons, this tells OpenGL which color it should fill the polygon)
// We have done quite a lot of setting so it's a good time to check if something went wrong, simply do this:
CheckGL();
font = LoadTexture("font.png"); if (glIsTexture( font.number ) == GL_FALSE) { std::cerr << "Unable to load font texture\n"; return -1; }
texture background, sheep, player, loppukuva;
background = LoadTexture("bg.bmp"); if (glIsTexture( background.number ) == GL_FALSE) { std::cerr << "Unable to load background texture\n"; return -1; }
sheep = LoadTexture("sheep.png"); if (glIsTexture( sheep.number ) == GL_FALSE) { std::cerr << "Unable to load sheep texture\n"; return -1; }
player = LoadTexture("charizar3d.png"); if (glIsTexture( player.number ) == GL_FALSE) { std::cerr << "Unable to load player texture\n"; return -1; }
loppukuva = LoadTexture("loppukuva.png"); if (glIsTexture( loppukuva.number ) == GL_FALSE) { std::cerr << "Unable to load loppukuva texture\n"; return -1; }
float player_x = screen->w - player.width;
float player_y = screen->h / 2.0f;
Uint8* keys = SDL_GetKeyState(NULL);
SDL_Event e;
bool end = false;
float seconds_elapsed = 0.0f;
Uint32 game_started_at = SDL_GetTicks();
Uint32 clock_time_elapsed = 0;
Uint32 last_clock_time = SDL_GetTicks();
while (!end)
{
clock_time_elapsed = SDL_GetTicks() - last_clock_time;
last_clock_time = last_clock_time + clock_time_elapsed;
seconds_elapsed = float (clock_time_elapsed) / 1000.0f;
glClear(GL_COLOR_BUFFER_BIT); // Clear the screen with the background color you chose
// glLoadIdentity();
while (SDL_PollEvent(&e))
{
if ((e.type == SDL_KEYDOWN) && (e.key.keysym.sym == SDLK_ESCAPE))
{
end = true;
}
}
if (keys[SDLK_LEFT])
player_x -= 100.0f * seconds_elapsed;
if (keys[SDLK_RIGHT])
player_x += 100.0f * seconds_elapsed;
if (keys[SDLK_UP])
player_y -= 100.0f * seconds_elapsed;
if (keys[SDLK_DOWN])
player_y += 100.0f * seconds_elapsed;
DrawBackground(background, screen->w, screen->h);
DrawTexture(sheep, 100, 100);
DrawTexture(player, player_x, player_y);
WriteText("LAMMASPELI", 0, 0);
std::stringstream ss;
ss << (SDL_GetTicks() - game_started_at) / 1000;
std::string str = ss.str();
WriteText("AIKAA KULUNUT: " + str + " SEKUNTIA", 600, 0);
if (((player_x - 100) * (player_x - 100) + (player_y - 100) * (player_y - 100)) < (200 * 200))
end = true;
SDL_Delay(1);
SDL_GL_SwapBuffers();
}
glClear(GL_COLOR_BUFFER_BIT); // Clear the screen with the background color you chose
DrawBackground(background, screen->w, screen->h);
DrawTexture(loppukuva, screen->w / 2 - loppukuva.width / 2, screen->h / 2 - loppukuva.height / 2);
Uint32 aika = SDL_GetTicks() - game_started_at;
std::stringstream ss;
ss << aika / 1000;
std::string str = ss.str();
WriteText("AIKAA KULUI: " + str + " SEKUNTIA", 600, 0);
WriteText("VOITIT PELIN! Press any key.", 400, 400);
WriteText("LAMMASPELI", 0, 0);
SDL_GL_SwapBuffers();
while (1)
{
while (SDL_PollEvent(&e))
{
if (e.type == SDL_KEYDOWN)
goto end;
}
}
end:
glDeleteTextures(1, &font.number );
glDeleteTextures(1, &background.number );
glDeleteTextures(1, &sheep.number );
glDeleteTextures(1, &player.number );
glDeleteTextures(1, &loppukuva.number );
SDL_Quit();
return 0;
}