Skip to content

Instantly share code, notes, and snippets.

@reefwing
Created August 25, 2012 05:52
Show Gist options
  • Save reefwing/3461386 to your computer and use it in GitHub Desktop.
Save reefwing/3461386 to your computer and use it in GitHub Desktop.
Tutorial 14 - An Extended Ship Class
--# Colors
-- Make available the predefined colors from UIColor
--
-- Version 1.1
blackColor = color(0, 0, 0)
darkGrayColor = color(85, 85, 85)
lightGrayColor = color(170, 170, 170)
whiteColor = color(255, 255, 255)
grayColor = color(128, 128, 128)
redColor = color(255, 0, 0)
greenColor = color(0, 255, 0)
blueColor = color(0, 0, 255)
cyanColor = color(0, 255, 255)
yellowColor = color(255, 255, 0)
magentaColor = color(255, 0, 255)
orangeColor = color(255, 128, 0)
purpleColor = color(128, 0, 128)
brownColor = color(153, 102, 51)
clearColor = color(0, 0, 0, 0)
lightTextColor = color(255, 255, 255, 153)
darkTextColor = color(0, 0, 0)
-- Reefwing specific Colours
lightRedColor = color(243, 157, 33)
lightBlueColor = color(0, 0, 255, 128)
--# Main
-- SpaceWar!
-- Define display mode and supported iPad orientations.
-- This way we don't forget to handle orientation changes if required.
-- "ANY" is the default assignment.
--displayMode(FULLSCREEN)
supportedOrientations(ANY)
function setup()
version = 1.0
saveProjectInfo("Description", "Codea SpaceWar v"..version)
saveProjectInfo("Author", "Reefwing Software")
saveProjectInfo("Date", "18th August 2012")
saveProjectInfo("Version", version)
saveProjectInfo("Comments", "Original Release.")
myShip = Ship(100, HEIGHT - 100)
enemyShip = Ship(WIDTH - 100, 100, true, 180)
starField = Twinkle(50)
end
-- This function gets called once every frame
function draw()
-- This sets a black background color & draws the star field
background(blackColor)
starField:draw()
-- Do your drawing here
myShip:draw()
enemyShip:draw()
if intersectRects(myShip.x, myShip.y, myShip.width, myShip.height,
enemyShip.x, enemyShip.y, enemyShip.width, enemyShip.height) then
print("BANG!!!")
end
end
function touched(touch)
myShip:touched(touch)
enemyShip:touched(touch)
end
--# Math
function pointInRect(pointX, pointY, x, y, w, h)
-- Returns true if point (pointX, pointY) is within the rectangle
-- with lower left corner at (x, y) with a width of w and a
-- height of h.
--
-- Reefwing Software (www.reefwing.com.au)
-- Version 1.0
if pointX >= x and pointX <= x + w and pointY >= y and pointY <= y + h then
return true
else
return false
end
end
function intersectRects(x1, y1, w1, h1, x2, y2, w2, h2)
if x1 + w1 >= x2 and x1 <= x2 + w2 and y1 + h1 >= y2 and y1 <= y2 + h2 then
return true
else
return false
end
end
function pointOffScreen(pointX, pointY)
-- Returns true if the point(pointX, pointY) is off screen.
if pointX < 0 or pointX > WIDTH or pointY < 0 or pointY > HEIGHT then
return true
else
return false
end
end
function math.hypot2(x, y)
-- This function also returns the hypotenuse of a right angle triangle
-- from (0, 0) to (x, y).
--
-- math.hypot2() is mathematically equivalent to math.hypot() but
-- reduces the chance of an over or underflow, since y/x can't overflow
-- and the square root is computed over a value between 1 and 2.
--
-- Reefwing Software (www.reefwing.com.au)
-- Version 1.0
x = math.abs(x)
y = math.abs(y)
t = math.min(x, y)
x = math.max(x, y)
y = t
return x * math.sqrt(1 + (y/x)*(y/x))
end
function math.polar(x, y, originX, originY)
-- Usage: math.polar(x, y) - origin is assumed at (0, 0)
-- math.polar(x, y, originX, originY)
--
-- This function converts from cartesian co-ordinates (x, y) to
-- polar co-ordinates (distance, angle) using the two functions:
--
-- 1. distance = hypot(x, y) - the hypotenuse of a right-angle triangle; and
-- 2. angle = atan2(x, y) - is the arc tangent of y/x in radians.
--
-- Since nil evaluates to false in Lua, you can use "or" to assign a default value.
--
-- Reefwing Software (www.reefwing.com.au)
-- Version 1.0
local oX = originX or 0
local oY = originY or 0
local dx = x - oX
local dy = y - oY
local distance = math.hypot2(dx, dy)
local angleInDegrees = math.deg(math.atan2(dy, dx))
-- Functions may return multiple results in Lua.
return distance, angleInDegrees
end
--# Ship
Ship = class()
function Ship:init(x, y, enemy, heading)
-- you can accept and set parameters here
self.x = x or 0
self.y = y or 0
self.enemy = enemy or false
self.speed = 3
self.heading = heading or 0
self.mode = CORNER -- Supported co-ordinate modes are CENTER or CORNER
self.width = 50
self.height = 35
self.selected = false
self.imageMesh = mesh()
self.destination = nil
self.shipMoving = false
-- Ship Image Mesh Vertices
self.imageMesh.vertices = {vec2(0, 0), vec2(0, self.height), vec2(self.width, self.height/2),
vec2(0, 0), vec2(self.height/2, self.height/2),
vec2(0, self.height)}
-- Set the colour of every vertex in the mesh
-- red for enemy ships, blue for friendly.
if enemy then
shipColorTable = {whiteColor, whiteColor, redColor,
blackColor, blackColor, blackColor,}
else
shipColorTable = {blueColor, blueColor, lightBlueColor,
blackColor, blackColor, blackColor,}
end
self.imageMesh.colors = shipColorTable
end
-- If a destination is set, the ship will automatically move
-- towards this point each frame.
function Ship:updatePosition()
local distance, heading = math.polar(self.destination.x, self.destination.y, self.x, self.y)
if distance <= self.width or pointOffScreen(self.x, self.y) then
self.shipMoving = false -- approximate destination reached
else
self.heading = heading
if self.destination.x > self.x then
self.x = self.x + self.speed
elseif self.destination.x < self.x then
self.x = self.x - self.speed
end
if self.destination.y > self.y then
self.y = self.y + self.speed
elseif self.destination.y < self.y then
self.y = self.y - self.speed
end
end
end
function Ship:draw()
-- Codea does not automatically call this method
-- Draw the ship at the current (x,y) co-ordinates,
-- once updated if it is moving.
pushStyle()
pushMatrix()
if self.shipMoving then
self:updatePosition()
end
if self.mode == CORNER then
translate(self.x, self.y)
elseif self.mode == CENTER then
translate(self.x + self.width/2, self.y + self.height/2)
else
print("ERROR:: Ship translation failed - unsupported co-ordinate mode.")
end
rotate(self.heading)
-- draw rectangle indicating selected ship
if self.selected then
stroke(greenColor)
strokeWidth(3)
fill(clearColor)
rect(-10, -10, self.width + 20, self.height +20)
end
-- draw ship
self.imageMesh:draw()
popMatrix()
popStyle()
end
function Ship:touched(touch)
-- Codea does not automatically call this method
-- pointInRect() function is located in Collisions
if not self.enemy and touch.state == ENDED then
-- if touch is on the rectangle bounding the ship
if pointInRect(touch.x, touch.y, self.x, self.y, self.width, self.height) then
if self.selected then
self.selected = false
else
self.selected = true
end
elseif self.selected then -- if selected set ship destination
local dx, dy
if self.mode == CORNER then
dx, dy = touch.x - self.width/2, touch.y - self.height/2
else
dx, dy = touch.x, touch.y
end
if self.destination == nil then
self.destination = vec2(dx, dy)
else
self.destination.x, self.destination.y = dx, dy
end
self.shipMoving = true
print("Ship destination - x: "..self.destination.x.." y: "..self.destination.y)
end
end
end
--# Twinkle
Twinkle = class()
-- Twinkle Class courtesy of Ipad41001
-- December 2011
--
-- Creates a nice twinkling star background.
--
-- Modified: numberOfStars variable added
--
-- Version 1.1
function Twinkle:init(numberOfStars)
-- you can accept and set parameters here
st = {}
ns = numberOfStars -- number of stars
for i = 1,ns do
if math.random(2) == 1 then g = .25 else g = -.25 end
l = 5 + (math.random(39)/4)
st[i] = {g=g,l=l,x=math.random(WIDTH),y=math.random(HEIGHT)}
end
end
function Twinkle:draw()
-- Codea does not automatically call this method
pushStyle()
rect(0,0,1,1)
-- background(20, 46, 181, 255)
background(0, 0, 0)
strokeWidth(3)
lineCapMode(SQUARE)
stroke(255, 255, 255, 255)
fill(255, 255, 255, 255)
for i = 1,ns do
if st[i].l <= 5 and math.random(2) == 1 then st[i].g = .25
elseif st[i].l >= 15 and math.random(2) == 1 then st[i].g = -.25 end
st[i].l = st[i].l + st[i].g
ll = (15 - st[i].l)/2
line(st[i].x-st[i].l,st[i].y,st[i].x+st[i].l,st[i].y)
line(st[i].x,st[i].y-st[i].l,st[i].x,st[i].y+st[i].l)
line(st[i].x-ll,st[i].y-ll,st[i].x+ll,st[i].y+ll)
line(st[i].x+ll,st[i].y-ll,st[i].x-ll,st[i].y+ll)
ellipse(st[i].x,st[i].y,6,6)
end
popStyle()
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment