Created
December 17, 2011 14:35
-
-
Save cadwallion/1490347 to your computer and use it in GitHub Desktop.
Peter Cooper's jRuby Pong, Refactored
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'java' | |
require 'lwjgl.jar' | |
require 'slick.jar' | |
java_import org.newdawn.slick.Image | |
require 'pong/image_context' | |
require 'pong/collidable_attributes' | |
module Pong | |
class Ball | |
include Pong::ImageContext | |
include CollidableAttributes | |
attr_accessor :x, :y, :velocity, :angle | |
def initialize | |
@image = Image.new('ball.png') | |
reset | |
end | |
def reset | |
@x = 200 | |
@y = 200 | |
@angle = 45 | |
@velocity = 0.3 | |
end | |
def move(delta) | |
@x += @velocity * delta * Math.cos(@angle * Math::PI / 180) | |
@y -= @velocity * delta * Math.sin(@angle * Math::PI / 180) | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Pong | |
# Used for collision detection of the ball to the container and the ball to the paddle. | |
# This module assumes the existence of dimension attributes (x, y, width, height) | |
# | |
# @TODO: Extract this into GameUtils | |
module CollidableAttributes | |
def is_colliding_with? entity | |
x >= entity.x && x <= (entity.x + entity.width) && y.round >= (entity.y - height) | |
end | |
def colliding_with_container? container | |
%w{left right top bottom}.each do |direction| | |
return true if container_collision(container, direction) | |
end | |
return false | |
end | |
def container_collision(entity, edge) | |
case edge | |
when 'left' | |
return x < 0 | |
when 'right' | |
return x > entity.width - width | |
when 'top' | |
return y < 0 | |
when 'bottom' | |
return y > entity.height | |
else | |
return false | |
end | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Pong | |
# Images in Slick2D work differently than...well, any other game library I've worked with. Instead of | |
# explicitly binding images to the window context, it implicitly binds them by only allowing a single | |
# container to be instantiated. | |
# | |
# ImageContext handles delegation of coordinates and sizing of an object to the image context. In Pong, | |
# we use this for the Pong and Paddle | |
module ImageContext | |
attr_accessor :image | |
def width | |
@image.width | |
end | |
def height | |
@image.height | |
end | |
# Assumes `x` and `y` methods in the included method | |
def draw | |
@image.draw(x, y) | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$:.push File.expand_path('../lib', __FILE__) | |
require 'java' | |
require 'lwjgl.jar' | |
require 'slick.jar' | |
require 'pong' | |
# Screwing with the Java library integration | |
java_import org.newdawn.slick.AppGameContainer | |
# Slick2D isolates the game class from the window context that renders it | |
# This is different from Gosu that mixes it within the Gosu::Window class | |
app = AppGameContainer.new(Pong::Game.new) | |
app.set_display_mode(640, 480, false) | |
app.start |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'java' | |
require 'lwjgl.jar' | |
require 'slick.jar' | |
java_import org.newdawn.slick.Image | |
require 'pong/image_context' | |
require 'pong/collidable_attributes' | |
module Pong | |
class Paddle | |
include Pong::ImageContext | |
include CollidableAttributes | |
attr_accessor :x, :y, :velocity | |
def initialize | |
@image = Image.new('paddle.png') | |
@y = 400 | |
reset | |
end | |
def reset | |
@x = 200 | |
@velocity = 0.3 | |
end | |
def move(delta) | |
@x += velocity * delta | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'java' | |
require 'lwjgl.jar' | |
require 'slick.jar' | |
require 'pong/ball' | |
require 'pong/paddle' | |
java_import org.newdawn.slick.BasicGame | |
java_import org.newdawn.slick.GameContainer | |
java_import org.newdawn.slick.Graphics | |
java_import org.newdawn.slick.Image | |
java_import org.newdawn.slick.Input | |
java_import org.newdawn.slick.SlickException | |
module Pong | |
# We subclass BasicGame so we can let Slick2D handle the rendering and main game loop | |
# This means we need to define `render`, `init`, and `update`. | |
class Game < BasicGame | |
def initialize | |
super('RubyPong') | |
end | |
# This method is called continuously. Rule of thumb: Always redraw the screen from blank. You do not | |
# because you do not know if `update` will have been called. | |
def render(container, graphics) | |
@bg.draw(0, 0) | |
@ball.draw | |
@paddle.draw | |
graphics.draw_string('RubyPong (ESC to exit)', 8, container.height - 30) | |
end | |
# Establishes the connection between container and game state. Creates our game objects. We have `init` | |
# AND `initialize` because Java sucks at naming... | |
# | |
# @param [AppContainer] - The AppContainer state | |
def init(container) | |
@bg = Image.new('bg.png') | |
@ball = Pong::Ball.new | |
@paddle = Pong::Paddle.new | |
end | |
# This is your game logic method. This will be called continuously in the main game loop and should be | |
# the entry point for input handling and game state change. Do NOT put rendering logic in the update method | |
# due to the nature of update vs render running potentially simultaneously | |
# | |
# @param [AppContainer] - The AppContainer game state | |
# @param [Float] - The time since last update call | |
def update(container, delta) | |
handle_input(container, delta) | |
@ball.move(delta) | |
collision_detection(container) | |
end | |
# Handles input to move the paddle left/right and game exit. | |
# Controls: [LEFT/A] for left, [RIGHT/D] for right, [ESC] to exit | |
# | |
# Input handler. Every key is mapped to a constant in the Input class. This method is not an override, but | |
# it's a good idea to isolate your input handler from your game logic as it will be the second most bloated | |
# point for game logic | |
# | |
# @param [AppContainer] - The AppContainer game state | |
# @param [Float] - Time since last update call | |
def handle_input(container, delta) | |
input = container.get_input | |
container.exit if input.is_key_down(Input::KEY_ESCAPE) | |
@paddle.move(-delta) if (input.is_key_down(Input::KEY_LEFT) || input.is_key_down(Input::KEY_A)) && [email protected]_collision(container, 'left') | |
@paddle.move(delta) if (input.is_key_down(Input::KEY_RIGHT) || input.is_key_down(Input::KEY_D)) && [email protected]_collision(container, 'right') | |
end | |
# Collision detection for the ball staying within the window container | |
# | |
# @param [container] - the AppContainer object state | |
def collision_detection(container) | |
if @ball.colliding_with_container? container | |
@ball.angle = (@ball.angle + 90) % 360 | |
end | |
if @ball.container_collision(container, 'bottom') | |
@paddle.reset | |
@ball.reset | |
end | |
if @ball.is_colliding_with? @paddle | |
@ball.angle = (@ball.angle + 90) % 360 | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment