diff --git a/conf.lua b/conf.lua new file mode 100644 index 0000000..53fd19b --- /dev/null +++ b/conf.lua @@ -0,0 +1,17 @@ +-- LÖVE configuration values + +function love.conf(t) + -- Disable unneeded modules + t.modules.joystick = false + + t.window.title = "Fysplane" + t.window.width = 1024 + t.window.height = 768 + t.window.resizable = false + + -- LÖVE version + t.version = "0.9.1" + + -- Game save directory name + t.identity = "fysplane" +end \ No newline at end of file diff --git a/entities/entity.lua b/entities/entity.lua new file mode 100644 index 0000000..c57d560 --- /dev/null +++ b/entities/entity.lua @@ -0,0 +1,42 @@ +Class = require 'hump.class' + +-- Entity is the basic building block of all objects in fysplane. All other +-- objects in game that are not part of the background derive from this class. + +entity_id = 1 + +Entity = Class{ + init = function(self, x, y, level) + self.x = x + self.y = y + self.level = level + + self.id = entity_id + entity_id = entity_id + 1 + + self.level.entity_list[self.id] = self + end; + + draw = function(self) + end; + + update = function(self, dt) + end; + + delete = function(self) + self.level.entity_list[self.id] = nil + end; +} + +function drawEntities() + -- Do we need ordering? If so, use ipairs instead of pairs + for key, entity in pairs(entity_list) do + entity:draw() + end +end + +function updateEntities(dt) + for key, entity in pairs(entity_list) do + entity:update(dt) + end +end diff --git a/entities/fixedentity.lua b/entities/fixedentity.lua new file mode 100644 index 0000000..ad427c7 --- /dev/null +++ b/entities/fixedentity.lua @@ -0,0 +1,18 @@ +Class = require 'hump.class' +require 'entities/entity' + +FixedEntity = Class{ + __includes = Entity, + + init = function(self, x, y, level) + Entity.init(self, x, y, level) + end; + + draw = function(self) + -- Noop, implement in child + end; + + update = function(self, dt) + -- Noop, implement in child + end; +} diff --git a/entities/physicsentity.lua b/entities/physicsentity.lua new file mode 100644 index 0000000..4c1877f --- /dev/null +++ b/entities/physicsentity.lua @@ -0,0 +1,62 @@ +Class = require 'hump.class' +require 'entities/entity' +require 'utils' + +PhysicsEntity = Class{ + __includes = Entity, + + init = function(self, x, y, level, physics_type, restitution) + Entity.init(self, x, y, level) + self.physicsType = physics_type + self.main_color = main_color + self.restitution = restitution + + self:initPhysics(self) + end; + + initPhysics = function(self) + self.body = love.physics.newBody(self.level.world, self.x, self.y, + self.physicsType) + end; + + -- This should only be called once the child has created their shapes, maybe + -- in the child constructor + -- You can add a density too. I don't know what that means + attachShape = function(self, density) + density = density or 1 + self.fixture = love.physics.newFixture(self.body, self.shape, density) + self.fixture:setRestitution(self.restitution) + + -- Add reference to this object so we can get it in collisions + self.fixture:setUserData(self) + end; + + -- Reimplement + draw = function(self) + love.graphics.setColor({255, 255, 255, 255}) + end; + + -- Only update if physics is not static + update = function(self, dt) + if self.physicsType ~= "static" then + self.x = self.body:getX() + self.y = self.body:getY() + end + end; + + delete = function(self) + if self.body ~= nil then + self.body:destroy() + end + + Entity.delete(self) + end; + + + -- Apply linear impulse with given direction and power + punch = function(self, angle, power) + local forces = deg_dist_to_xy(angle, power) + self.body:applyLinearImpulse(forces[1], forces[2]) + end; +} + diff --git a/hump/class.lua b/hump/class.lua index b3ac5c2..674dc33 100644 --- a/hump/class.lua +++ b/hump/class.lua @@ -76,8 +76,8 @@ local function new(class) else table.insert(class.class_tree, class_id) end - class.class_id = class_id + class.class_id = class_id class_id = class_id + 1 -- Check if object is instance of given class @@ -95,8 +95,6 @@ local function new(class) return false end - class_id = class_id + 1 - -- constructor call return setmetatable(class, {__call = function(c, ...) local o = setmetatable({}, c) diff --git a/settings.lua b/settings.lua new file mode 100644 index 0000000..926a8e7 --- /dev/null +++ b/settings.lua @@ -0,0 +1,6 @@ +-- Game specific settings go here +-- LÖVE settings should go to conf.lua + +PIXELS_PER_METER = 10 + + diff --git a/utils.lua b/utils.lua new file mode 100644 index 0000000..5199671 --- /dev/null +++ b/utils.lua @@ -0,0 +1,77 @@ +--[[ +Some random utilities that can be useful +]] + + + +-- Calculate XY position from given degrees (not rad!) and distance +-- Returns tuple {X, Y} coordinates +-- Note that either may be negative +function deg_dist_to_xy(degrees, distance) + local rad = deg_to_rad(degrees) + return rad_dist_to_xy(rad, distance) +end + +function rad_dist_to_xy(radians, distance) + return {distance * math.cos(radians), distance * math.sin(radians)} +end + +-- Convert degrees to radians +function deg_to_rad(degrees) + return degrees * math.pi / 180 +end + +function rad_to_deg(radians) + return radians * 180 / math.pi +end + +-- Convert X,Y to rad from horizontal axle (pointing right) +function xy_to_rad(x, y) + -- Avoid division by 0 + if x == 0 then + if y >= 0 then + return math.pi / 2 + else + return math.pi * 1.5 + end + else + local angle = math.atan(math.abs(y) / math.abs(x)) + + -- Take into account the quadrant we are in + if x >= 0 and y < 0 then + return 2 * math.pi - angle + elseif x < 0 and y < 0 then + return math.pi + angle + elseif x < 0 and y >= 0 then + return math.pi - angle + else + return angle + end + end +end + +function xy_to_deg(x, y) + return rad_to_deg(xy_to_rad(x, y)) +end + +-- Get distance between two points +function distance(x1, y1, x2, y2) + return math.sqrt(math.pow(x1 - x2, 2) + math.pow(y1 - y2, 2)) +end + +-- Get objects within a radius from given coordinates in given level +function getObjectsInRadius(x, y, radius, level, include_player) + include_player = include_player or false + local objs = level.world:getBodyList() + local ret = {} + for _, body in pairs(objs) do + if distance(x, y, body:getX(), body:getY()) <= radius then + if body:getFixtureList()[1]:getUserData() ~= player + or include_player then + table.insert(ret, body) + end + end + end + + return ret +end