// Workshop 3 part 2 import sdljava.*; import sdljava.video.*; import sdljava.event.*; class s03_p02 { // Our SDL surface for drawing on protected static SDLSurface screen; // The speed of our object protected static float speed_x, speed_y, max_speed; // The position of our object protected static float position_x, position_y; // We will call this function whenever we want to exit the program. // It uninitialises SDL and forces a program exit. public static void exit(int value) { SDLMain.quit(); System.out.println("Exiting.."); System.exit(value); } // In this function, we retrieve and handle events. // The function returns true if the user wishes to exit the program. public static boolean handle_events() { try { // SDL stores events in a queue. // To look at events we have two options: // 1. We can wait for events, in which case we call a function that will not return until there is an event. // 2. We can have a quick look at the event queue, using a function that will retrieve an event if there is one, returning null if there isn't. // // In an interactive game, it's not much use if we get stuck waiting for events, as we won't be able to draw or update the scene. // Therefore, we want to use the 'quick look' option. // This is called polling for events. // The waiting technique is known as blocking. // Both methods remove the oldest event from the queue and give it to us to decide what to do with it. // Poll for events SDLEvent event = SDLEvent.pollEvent(); // If there was an event.. if( event != null ) // What we do depends on the type switch( event.getType() ) { case SDLEvent.SDL_QUIT: // This event type is generated when the user clicks on the 'x' to close the window. // We want to exit our handle_events function, returning true to indicate that the user wishes to quit. return true; case SDLEvent.SDL_KEYDOWN: // The user has pressed a key { // This means that the event is actually of a sub-type called an SDLKeyboardEvent. // If we cast the event to this type, we can retrieve the actual key type int key = ((SDLKeyboardEvent) event).getSym(); // What we do now depends on the key that was pressed switch( key ) { case SDLKey.SDLK_ESCAPE: exit(0); case SDLKey.SDLK_UP: speed_y += -max_speed; break; case SDLKey.SDLK_DOWN: speed_y += max_speed; break; case SDLKey.SDLK_LEFT: speed_x += -max_speed; break; case SDLKey.SDLK_RIGHT: speed_x += max_speed; break; default: System.out.println(key); } } break; case SDLEvent.SDL_KEYUP: // The user has released a key { // This means that the event is actually of a sub-type called an SDLKeyboardEvent. // If we cast the event to this type, we can retrieve the actual key type int key = ((SDLKeyboardEvent) event).getSym(); // What we do now depends on the key that was pressed switch( key ) { case SDLKey.SDLK_UP: speed_y -= -max_speed; break; case SDLKey.SDLK_DOWN: speed_y -= max_speed; break; case SDLKey.SDLK_LEFT: speed_x -= -max_speed; break; case SDLKey.SDLK_RIGHT: speed_x -= max_speed; break; // Letter keys are: SDLK_[letter] e.g. SDLK_g is g // See the SDL Java documentation for more details: http://sdljava.sourceforge.net/docs/api/ } } break; case SDLEvent.SDL_MOUSEBUTTONDOWN: // The user has pressed a mouse button break; case SDLEvent.SDL_MOUSEBUTTONUP: // The user has released a mouse button break; } } catch(SDLException e) { System.err.println("Error while polling event : " + SDLMain.getError()); exit(1); } return false; } // In this function, we update our scene public static void update( float deltaT_s ) { // Update the position of our object position_x += deltaT_s * speed_x; position_y += deltaT_s * speed_y; } // In this function, we draw our scene // Upon encountering an error, this function throws an SDLException, which is passed on from SDL function calls public static void draw() throws sdljava.SDLException { // First, we clear the screen screen.fillRect(screen.mapRGB(0,0,0)); // Our object will be a rectangle, so create it at the correct position SDLRect rectangle = new SDLRect((int)position_x,(int)position_y,30,10); // Draw it, specifying the colour screen.fillRect(rectangle,screen.mapRGB(255,255,255)); // That flip command again.. screen.flip(); } public static void main(String[] args) { // Initialise our variables to zero speed_x = speed_y = 0.0f; // The maximum speed of our object: this is in pixels per second max_speed = 400.0f; // The initial position of our object. // This should put it in the centre of the window position_x = 320; position_y = 240; // Create an SDLMain object SDLMain sdl = new SDLMain(); // SDL uses exceptions when it encounters problems try { // Initialise SDL to use its video (graphics) capabilities sdl.init(SDLMain.SDL_INIT_VIDEO); // SDL uses what it calls a 'surface' as a window. screen = SDLVideo.setVideoMode(640, 480, 0, 0 ); // Timing is one of the most crucial aspects of an interactive game-like program. // Since the graphics on screen can take a variable amount of time to draw, // we cannot rely on a constant frame rate. Besides, if we run our program on a // faster or slower machine, it will be different anyway. // We must therefore calculate the amount of time that has elapsed between each // iteration of our game loop, and use this when we update our scene. long previous_time = 0, current_time = 0, deltaT = 0; float deltaT_s = 0.0f; // (delta in mathematics means 'change', so this is the change in time, measured in seconds) // Retrieves the time current_time = System.currentTimeMillis(); previous_time = current_time; // This will store whether or not the user has asked to quit boolean quit = false; // This is our main "game loop", and we will run it // while we've not been asked to quit... while( quit == false ) { // When the user presses a key, or uses the mouse, that input is stored in SDL as an 'event'. // As an interactive program, we need to look at these events and decide what to do about them. // Our function here also returns true if we want to quit: quit = handle_events(); // In an interactive program, be it a game or whatever, we usually have a variety of things to update each frame. // These could be character animations, physics simulations, explosions, whatever we want... update(deltaT_s); // Finally, we need to draw our scene draw(); // Update our current time current_time = System.currentTimeMillis(); // Work out the frame time for that frame deltaT_s = (float)(current_time-previous_time)/1000.0f; // For the next frame, our current time will the the previous one previous_time = current_time; } exit(0); } catch(SDLException e) // Catch SDL problems { // We shall handle any problems by printing a stack trace: e.printStackTrace(); // and an explanation if that wasn't enough System.err.println("SDL encountered a problem"); exit(1); } } }