Created
August 25, 2012 05:52
-
-
Save reefwing/3461386 to your computer and use it in GitHub Desktop.
Tutorial 14 - An Extended Ship Class
This file contains 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
--# 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) |
This file contains 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
--# 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 |
This file contains 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
--# 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 |
This file contains 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
--# 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 |
This file contains 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
--# 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