My projects and demos

Show off your games, demos and other (playable) creations.
User avatar
bartbes
Sex machine
Posts: 4946
Joined: Fri Aug 29, 2008 10:35 am
Location: The Netherlands
Contact:

Re: My projects and demos

Post by bartbes »

I'd have quoted but your post was long enough to make that annoying :P.

As for the 'Entities' error, that's not hump.gamestate's fault, that file does reference a (global) 'Entities', which is never defined in the file. Is it meant to be a global originating from another file? Did you forget to require something?

As for the error in the example code, that's also your fault, if we're talking about the example here anyway, because you forgot an important part of the first line: you need to assign the result of require to a variable called 'Gamestate'.
User avatar
Pangit
Party member
Posts: 148
Joined: Thu Jun 16, 2016 9:20 am

Re: My projects and demos

Post by Pangit »

gamestate_exa.love
(13.54 KiB) Downloaded 115 times
If its not explained in the documentation how am I supposed to know that the example is incomplete?

I included Gamestate but it still did not work...

Thank you for explaining it was all my fault, but could you perhaps show me a working example? If it is so obvious I am confused why nobody does this usually.

Like its a 32 line file with spacing. How hard is it to provide a complete working example? How is a person supposed to learn when there are few tutorials, and examples are incomplete or assume you already know the library & framework.

Its ok though because there are a great many books on the framework to learn from...

LÖVE for Lua Game Programming by Darmie Akinlaja. - In the words of Mr.T "I pitty the fool." that tries to use that book to learn love. While no doubt at the time of its release it was a fairly useful book its now hopelessly out of date and it looks like the author and the publisher has no desire to update it so it might actually be useful.

If there are any other books on the framework that I missed or tutorials that are complete and were actually tested - not just a talking shop for ideas & concepts then I am all ears.

By tutorials I mean something that will end up producing a working program that is non trivial that will enable someone to write a program using the framework properly. Ideally not a clone of a game that was written 30-40 years ago.

Lets say I cast the net wider - I look at not just love but lua. How many lua books can even come close to something like C++ Primer, 5th Edition in terms of completeness and scope? It's not like a book like this could not be written for lua or love. So I was curious why there are so few, books, tutorials available. You could argue but its open source... but then look at python. There are literally hundreds of books available on every topic under the sun. (ok a good portion are pretty terrible. But there are enough to get things done - its just a pity its slow.)

Code: Select all

Gamestate=require "gamestate"

local menu = {} -- previously: Gamestate.new()
local game = {}

function menu:draw()
    love.graphics.print("Press Enter to continue", 10, 10)
end

function menu:keyreleased(key, code)
    if key == 'return' then
        Gamestate.switch(game)
    end
end

function game:enter()
    Entities.clear()
    -- setup entities here
end

function game:update(dt)
    Entities.update(dt)
end

function game:draw()
    Entities.draw()
end

function love.load()
    Gamestate.registerEvents()
    Gamestate.switch(menu)
end
User avatar
Pangit
Party member
Posts: 148
Joined: Thu Jun 16, 2016 9:20 am

Re: My projects and demos

Post by Pangit »

Another day - another crack at the problem.

I figured time to take a slightly different aproach.

In love.load() I added the following

Code: Select all

    magamestate = {
        splash = true,
        splash2 = false,
        splash3 = false,
        mainMenu = false,
        subMenuCharacterStats = false,
        gamescreen = false,
        quitscreen = false,
        subMenuHelp = false,
        tutorial = false,
        combat = false,
        dead = false,
        trade = false,
        judge = false,
        cutscene = false
    }
and in function love.draw() I altered it to the following...

Code: Select all

function love.draw()

    if magamestate.splash == true then
        cam:attach()
        color = {0, 50, 0}
        love.graphics.setFont(introfont)
        love.graphics.setBackgroundColor(color)
        love.graphics.print("SPLASH SCREEN 1", 100, 500)
        Timer.after(5, function() magamestate.splash = false magamestate.splash2 = true end)
        --magamestate.splash = false
        --magamestate.mainMenu = true
        
        cam:detach()
    end

    if magamestate.splash2 == true then
        cam:attach()
        color = {50, 0, 0}
        love.graphics.setFont(introfont)
        love.graphics.setBackgroundColor(color)
        love.graphics.print("SPLASH SCREEN 2", 100, 500)
        Timer.after(5, function() magamestate.splash2 = false magamestate.splash3 = true end)
        --magamestate.splash = false
        --magamestate.mainMenu = true
        
        cam:detach()
    end

    if magamestate.splash3 == true then
        cam:attach()
        color = {0, 0, 50}
        love.graphics.setFont(introfont)
        love.graphics.setBackgroundColor(color)
        love.graphics.print("SPLASH SCREEN 3", 100, 500)
        Timer.after(5, function() magamestate.splash3 = false magamestate.subMenuCharacterStats = true end)
        --magamestate.splash = false
        --magamestate.mainMenu = true
        
        cam:detach()
    end
    if magamestate.subMenuCharacterStats == true then
    color = {255, 255, 255}
    cam:attach()   -- Required to see what the camera is doing.
    -- This is where we test the program window to obtain the dimensions.
    local screenWidth = love.graphics.getWidth()
    local screenHeight = love.graphics.getHeight()
    -- This is where the maths is done to calculate the scaling values used.
    local ratio = math.min(screenWidth/internalWidth, screenHeight/internalHeight)
    -- This is where the scaling takes place
    love.graphics.scale(ratio,ratio)
    -- Set the background colour as we are using transparencies
    love.graphics.setBackgroundColor(color)
    -- Draw the base layer background.
    love.graphics.draw(mbackground, 0, 0)
    -- Draw the updated screens.
    love.graphics.draw(screens[current_screen])
    -- Draw the mouse coordinates.
    --mousey()
    drawicons()
    love.graphics.setFont(font)
    love.graphics.print(player.credits, 505, 115)
    love.graphics.print(player.xptonext, 945, 115)
    love.graphics.print(player.xp, 1325, 115)
    --love.graphics.setFont(sansfont)
    --love.graphics.print("THISISATEST", 500, 500)
    love.graphics.setColor(255,255,255,fade.alpha)
    cam:detach()   -- Stop rendering the camera.
    end
end
This gives a simple splash screen by manipulating a bunch of flags and checking for the state via conditionals.

The nice thing is I can set as many flags as there are grains of sand on a beach and have a lot of control over the program flow logic that way. By loading general functions from within these states it should be ok. I can build the functionality up in stages and with them all using the same common functions when improvements are made to one function used by the scene states it gets propagated to all within the program.

The nasty part about this is its a inelegant way to handle the problem. It also clutters up function love.draw() I would have preferred to have all of the draw code within its own table that just gets looked up when love.draw needs to. But need to figure out how to implement that. Once I can do that I can just load the game layout from a file when the program runs and give it much greater flexibility + aid updating at a future date.

One thing I have been looking at today that gave me a few ideas how to make the game easy to develop was looking at the way XSE (one of the pokemon scripting language) worked. The RPG message tutorial I was playing with yesterday gave me the idea. Its a pretty full featured way to implement a scrip-table RPG game. I could potentially make a similar thing for my program. This would enable me to work separately on the game content vs the engine - making updates much more manageable. Just need to figure out a way to implement it without using coroutine voodoo.
User avatar
MadByte
Party member
Posts: 533
Joined: Fri May 03, 2013 6:42 pm
Location: Braunschweig, Germany

Re: My projects and demos

Post by MadByte »

Just in case:
Gamestate Example.love
(3.09 KiB) Downloaded 1147 times
Notes:
  • If you don't want to use multiple files just copy paste each gamestate into your main.lua (exect the last line i.g "return Game" etc.)
  • Make sure to always define your tables and pass them correctly . that was your problem with the "Entities" table.
Hope that helps a bit.
User avatar
Pangit
Party member
Posts: 148
Joined: Thu Jun 16, 2016 9:20 am

Re: My projects and demos

Post by Pangit »

Thank you very much for your help MadByte that helps a whole bunch.

Probably a good point to update:

Spent the day working on getting some extra functionality into the program. Seemingly minor but quite useful..
To avoid going over the same subject twice you can re-live the magic that was my question & enlightenment + my solution to the problem here...

Image
viewtopic.php?f=4&p=200480#p200480

New demo is on the first post of this thread.

Here is the main.lua file.

Code: Select all

-- alphademo2_02.love.
---main.lua
-- This little demo shows the character stats extra info screens that would be part of my main game.
-- It implements some additional features that would be handled by separate modules in the program but for
-- convince sake they are included here in the main.lua file.

require".lib.TEsound.TEsound"
Camera = require ".lib.hump.camera"
Timer = require ".lib.hump.timer"
Signal = require '.lib.hump.signal'

introscreen = love.graphics.newImage("/assets/introduction_1.png")

--v help.
fade = {alpha = 255}

-- This is where I set the iconflags, they are used in the program to keep tabs on the state of various operations, at the moment
-- only nosound and issound are operational. loading, will be when a file is loading from the disk, saving will be when a file is
-- being written to the disk. problem is the error state from the program. Eventually that will be used to show a error code screen
 
iconflags = { 
    nosound = false,
    issound = true,
    loading = false,
    saving = false,
    problem = false,
    keyboard = false,
    mouse = false,
    gamepad = false,
    joystick = false,
    touch = false
}

-- This helps us guess if the player has access to a keyboard and mouse, we do this my taking an educated guess based on the OS that 
-- we have detected and go from there. 
-- OS X, Windows, Linux We can be fairly confident there will be a keyboard and mouse present. 
-- For Android & iOS we can be fairly sure there is not going to be a keyboard and mouse, if there is one the player could always set 
-- the option in the configuration screen manually later. But for 99% of players who are using Android & iOS platforms they are going
-- to be using touch interfaces.

function osPeek()
    osString = love.system.getOS()
    if osString == "OS X" then
        iconflags.keyboard = true
        icon_mouse = true
    elseif osString == "Windows" then
        iconflags.keyboard = true
        iconflags.mouse = true
    elseif osString == "Linux" then
        iconflags.keyboard = true
        iconflags.mouse = true
    elseif osString == "Android" then
        iconflags.keyboard = false
        iconflags.mouse = false
        iconflags.touch = true
    elseif osString == "iOS" then
        iconflags.keyboard = false
        iconflags.mouse = false
        iconflags.touch = true
    end
end


-- This is where we set the player variables, in the game this would be supplied by global game variables that the menu system would 
-- access. But as this is a demo, and the program structure is incomplete were just supply them here for now. 
-- One thing I need to find out is how to print leading zeros on the screen so that the positioning is correct when player starts the
-- game.
-- 
-- Another intresting issue is at the moment I am using the font functions to handle this display, ideally I should be using an 
-- image font to make scaling issues easyer but I have yet to sucessfully implement this. 

player = { credits = 100000000, xptonext = 10245000, xp = 9999999999 }

-- This is a table containing all of the text boxes that get swapped in & out while using the menu. 
-- the table length is used to set the mod for the naviagion. I don't need to hardcode anything the program queries this structure to 
-- check the length then uses that as the modular. Quite nice. If you need to add more screens just add an additional line to the screens 
-- table and you are good to go.

screens = {
  love.graphics.newImage("/assets/charactersheetb_3a.png"),
  love.graphics.newImage("/assets/charactersheetb_3b.png"),
  love.graphics.newImage("/assets/charactersheetb_3c.png"),
  love.graphics.newImage("/assets/charactersheetb_3d.png"),
  love.graphics.newImage("/assets/charactersheetb_3e.png"),
  love.graphics.newImage("/assets/charactersheetb_3f.png"),
  love.graphics.newImage("/assets/charactersheetb_3g.png"),
  love.graphics.newImage("/assets/charactersheetb_3h.png"),
  love.graphics.newImage("/assets/charactersheetb_3i.png"),
  love.graphics.newImage("/assets/charactersheetb_3j.png"),
  love.graphics.newImage("/assets/charactersheetb_3k.png"),
  love.graphics.newImage("/assets/charactersheetb_3l.png"),
  love.graphics.newImage("/assets/charactersheetb_3m.png")
}

-- This variable is used as a counter in the navigation for the menu to control what postion in the screens table is used for the
-- love.graphics.draw(screens[current_screen]). Navigation works by messing with this counter. You change the number of this you change 
-- what asset is displayed.

current_screen = 1

-- This variable is a counter used in the music selection (when you press F8) this counter keeps track of what music is being played. 
-- I wanted to make the function like that of screens but I couldnt figure out how to implement it properly. Its sad because as it stands
-- this is not a dynamic part of the code - I had to hardcode the options so that will make updating difficult. 

current_music = 1

-- While this works, I would have liked the flexability of the screens structure, but I couldnt get it to work that way.
-- I still think there is a better way to do this. 

function music_list()
    if current_music == 1 then
         music_list_choice = "/assets/sounds/Restricted-Zone_Looping.mp3"
    end
    if current_music == 2 then 
         music_list_choice = "/assets/sounds/Walled-City-of-Doom_Looping.mp3"
    end
    if current_music == 3 then
         music_list_choice = "/assets/sounds/Deserted-Streets_Looping.mp3"
    end
end

--music_selection = music_list[current_music]

-- I give up I just can't seem to get a simple tween efect to work right. I must be doing somthing screwed up.
-- The plan was to do back to white transition, then load the character stats menu. 

function fadeinout2(tweentype)
    color = {0, 0, 0}
    Timer.tween(3, color, {255, 255, 255}, tweentype)
    Timer.after(3, function() Timer.tween(3, color, {0,0,0}, tweentype) end)
    Timer.after(6, function() color = {0, 0, 0} end)
    love.graphics.draw(introscreen, 0, 0)    
end

function fadeinout()
    color = {0, 0, 0}
    Timer.tween(3, color, {255, 255, 255}, 'in-out-quad')
    Timer.after(3, function() Timer.tween(3, color, {0,0,0}, 'in-out-quad') end)
    Timer.after(6, function() color = {0, 0, 0} end)
    love.graphics.draw(introscreen, 0, 0)    
end

function fadeout()
    Timer.tween(3, fade, {alpha=255}, 'in-out-quad', function()
    Timer.tween(3, fade, {alpha=0}, 'in-out-quad')end)
end

function fadein()
    Timer.tween(10, fade, {alpha=255}, 'in-out-quad', function()
    Timer.tween(10, fade, {alpha=0}, 'in-out-quad')end)
end

-- The tween transition efects kind of broke me last night, still cannot figure out how to implement them properly. 
-- Figured I would leave them in here to annoy me till I get them to work. 
-- eventually they will just live in there own little library that will be called by the various parts of the program. 

-- where all the heavy lifting/loading should happen that is not dependant on love.update()
function love.load()

    magamestate = {
        splash = true,
        splash2 = false,
        splash3 = false,
        mainMenu = false,
        subMenuCharacterStats = false,
        gamescreen = false,
        quitscreen = false,
        subMenuHelp = false,
        tutorial = false,
        combat = false,
        dead = false,
        trade = false,
        judge = false,
        cutscene = false
    }

    osPeek()

    icon_keyboard_small = love.graphics.newImage("/assets/keyboard_small.png")
    icon_mouse_small = love.graphics.newImage("/assets/mouse_small.png")
    icon_gamepad_small = love.graphics.newImage("/assets/gamepad_small.png")
    icon_joystick_small = love.graphics.newImage("/assets/joystick_small.png")
    icon_touch_small = love.graphics.newImage("/assets/touch_small.png")

    icon_nosound_small = love.graphics.newImage("/assets/nosound_small.png") 
    icon_sound_small = love.graphics.newImage("/assets/sound_small.png") 
    introfont = love.graphics.newFont(100)
    font = love.graphics.newFont(36)

    sansfont = love.graphics.newImageFont("/assets/fonts/36_sans.png", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")

--    fadein()
--    fadeout()
    --fadeinout2("out-in-linear")
    -- Here is where the constant for the dimensions of the graphics assets live.
    internalWidth = 1600
    internalHeight = 1200
    -- Here is where the hump.timer constants and variables live.      
    -- Here is where the hump.camera constants and variables live.
    cam = Camera(500,384, 1, math.pi/2)
    mframe = love.graphics.newImage("/assets/menuframe.png")
    mbackground = love.graphics.newImage("/assets/framebkg.png")
    -- Here we set up the variables and constants used in handling the music and sounds of the program. 
    sfxval = 0.1
    musicval = 0.1
    TEsound.volume("sfx",sfxval)
    TEsound.volume("music",musicval)
    music_list()
    TEsound.playLooping(music_list_choice , "music")
end

-- This function draws the icons on the screen, eventually it will show loading, saving ect..
-- I still cant figure out why the icons don't fade the same as the rest of the screen.
-- drawicons() first checks the state of the sfxval variable and the musicval variable to check if both are 0 or less. 
-- if both variables are 0 or less then the iconflags.nosound is set to true, and the iconflags.issound is set to false.
-- if either one of the variables sfxval or musicval is greater than 0 (meaning there is sound being output.. then the
-- iconflags.issound is set to true, and the iconflags.nosound is set to false.
-- The second part of this function draws either the icon_nosound_small image to the screen, or if iconflag.sound = true then
-- icon_sound_small is used instead.
-- I should make an error icon also for an error state for nill. Will get on with this later.
 
function drawicons()
    if iconflags.keyboard == true then
        love.graphics.draw(icon_keyboard_small, 0, 0)
    end

    if iconflags.mouse == true then
        love.graphics.draw(icon_mouse_small, 0, 0)
    end

    if iconflags.joystick == true then
        love.graphics.draw(icon_joystick_small, 0, 0)
    end

    if iconflags.gamepad == true then
        love.graphics.draw(icon_gamepad_small, 0, 0)
    end

    if iconflags.touch == true then
        love.graphics.draw(icon_touch_small, 0, 0)
    end

    if sfxval <= 0 and musicval <= 0 then
        iconflags.issound = false
        iconflags.nosound = true
    elseif sfxval > 0 or musicval > 0 then
        iconflags.issound = true
        iconflags.nosound = false
    end

    if iconflags.nosound == true then
        love.graphics.draw(icon_nosound_small, 0, 0)
    elseif iconflags.issound == true then
        love.graphics.draw(icon_sound_small, 0, 0)
    end
end

-- love.draw() where the screen is blit. Try to avoid to much heavy work here as its called 30 times a second.
-- I am not so happy with the messy code here, I think it could be improved.

function love.draw()

    if magamestate.splash == true then
        cam:attach()
        color = {0, 50, 0}
        ink = {100, 0, 0}
        love.graphics.setFont(introfont)
        love.graphics.setColor(ink)
        love.graphics.setBackgroundColor(color)
        love.graphics.print("SPLASH SCREEN 1", 100, 500)
       ink = {255, 255, 255}
        love.graphics.setColor(ink)
        Timer.after(3, function() magamestate.splash = false magamestate.splash2 = true end)  
        cam:detach()
    end

    if magamestate.splash2 == true then
        cam:attach()
        color = {50, 0, 0}
        ink = {0, 100, 0}
        love.graphics.setFont(introfont)
        love.graphics.setColor(ink)
        love.graphics.setBackgroundColor(color)
        love.graphics.print("SPLASH SCREEN 2", 100, 500)
        ink = {255, 255, 255}
        Timer.after(3, function() magamestate.splash2 = false magamestate.splash3 = true end)
        cam:detach()
    end

    if magamestate.splash3 == true then
        cam:attach()
        color = {0, 0, 50}
        love.graphics.setFont(introfont)
        love.graphics.setBackgroundColor(color)
        love.graphics.setColor(ink)
        love.graphics.print("SPLASH SCREEN 3", 100, 500)
       Timer.after(3, function() magamestate.splash3 = false magamestate.subMenuCharacterStats = true end) 
        cam:detach()
    end

    if magamestate.subMenuCharacterStats == true then
    color = {255, 255, 255}
    cam:attach()   -- Required to see what the camera is doing.
    -- This is where we test the program window to obtain the dimensions.
    local screenWidth = love.graphics.getWidth()
    local screenHeight = love.graphics.getHeight()
    -- This is where the maths is done to calculate the scaling values used.
    local ratio = math.min(screenWidth/internalWidth, screenHeight/internalHeight)
    -- This is where the scaling takes place
    love.graphics.scale(ratio,ratio)
    -- Set the background colour as we are using transparencies
    love.graphics.setBackgroundColor(color)
    -- Draw the base layer background.
    love.graphics.draw(mbackground, 0, 0)
    -- Draw the updated screens.
    love.graphics.draw(screens[current_screen])
    -- Draw the mouse coordinates.
    --mousey()
    drawicons()
    love.graphics.setFont(font)
    love.graphics.print(player.credits, 505, 115)
    love.graphics.print(player.xptonext, 945, 115)
    love.graphics.print(player.xp, 1325, 115)
    --love.graphics.setFont(sansfont)
    --love.graphics.print("THISISATEST", 500, 500)
    love.graphics.setColor(255,255,255,fade.alpha)
    cam:detach()   -- Stop rendering the camera.
    end
end

-- this is my very early attempt to start implementing mouse support its not used at the moment.
-- coordinate weirdness vs screen position somewhat put me off. I will use the suit library to handle mouse interactions I think as I 
-- used this succesfully before. It beats doing things manually.
-- note to self. Change the silly name for this function. I like fingermouse() better.

function mousey()
    fingermouse={}
    fingermouse[1]=love.mouse.getX()
    fingermouse[2]=love.mouse.getY()
    love.graphics.print(fingermouse[1], 100, 100)
    love.graphics.print(fingermouse[2], 200, 100)
end

-- love.update(dt) where all the fast stuff that needs to be constantly checked each dt tick needs to live. Avoid heavy processing of 
-- stuff that can live elsewhere otherwise madness awaits. I managed to crash the program more times trying to put stuff that should 
-- have gone elsewhere in love_update(dt).
-- functions currently hooking on love.update(dt), hump.camera, hump.timer, myJoystick() and TESound.cleanup(). Suit will need to hook into 
-- this when I implment it.
-- I am happy with the state of love.update(dt). program seems to be running ok.

function love.update(dt)
    cam:rotateTo(0)
    Timer.update(dt)
    myJoystick()
    TEsound.cleanup()
end

-- This is the joystick/gamepad code. As my gamepad is not regonised by the system. I use the lower level library joystick to control the 
-- input. As you can see its not fully implemented yet. Eventually this will live in its own library file and be called by each part of the
-- program that needs input from the device. But for now it lives here.
-- thank you to zork for the help in getting this working. There is a better, clearer way to implmenent this but I have yet to get around
-- to implmeenting the mans sugestions.
-- functionality of the myjoystick function - 
-- first we define a local variable i and j - these are used to check if the player has really ment to press the button. If you don't have this
-- then you would need ninja like reactions to use the gamepad/joystick as the function would react to poling every frame. As it stands you need
-- to press the button for 7 dt's to get the function to change states and play the sound. i is one way j is the other.
-- second we create an object joysticks that contains the input data from the gamepad/joystick. 
-- next we check joysticks to see if either button has been pressed? this is a bool value. 
-- it checks if the back shoulder is pressed left or right, it then sets current_screen counter 
-- to an updated value based on the modular derived from the length of the screens table. 
-- Next I play a sound efect for feedback for the player when they hit the button. This should really not be hardcoded but should be found
-- in a table thats loaded at the start of the program to enable greater flexability. Will implement this later. As it makes updating the 
-- code much easyer where I can update all of the sound effects for buttons in one place instead of all over the program.
-- the modular is hard coded, this is a mistake and it should update from a configuration table at the start of the program to enable
-- greater flexability. Will fix this later. 
-- Finally we clear the j and i variables - otherwise you have a messy variable left. Its a little bit obsessive as normally this would not matter
-- but its nice to keep things tidy. 

local i,j = 0,0
function myJoystick()
local joysticks = love.joystick.getJoysticks()
if #joysticks ~= 0 then
    local button1down = joysticks[1]:isDown(5)
    local button2down = joysticks[1]:isDown(6)
    local isgamepad = joysticks[1]:isGamepad( )

        if joysticks ~= nil then
            iconflags.joystick = true
        end

        if isgamepad == true then
            iconflags.gamepad = true
        end

        if button1down == true then
            i = i + 1 
            if i % 7 == 1 then
                current_screen = (current_screen - 2) % #screens +1
                TEsound.play("/assets/sounds/Creepy-Roll-Over-3.mp3", "sfx")
            end
        else
            i = 0
        end
        if button2down == true then
            j = j + 1
            if j % 7 == 1 then
                current_screen = current_screen % #screens + 1
                TEsound.play("/assets/sounds/Creepy-Roll-Over-4.mp3", "sfx")
            end
        else
            j = 0
        end
    end
end

-- sadly I have not gotten very far with mouse support.
-- This is an error I should have commented this out. WIll remove once I get SUIT up and running.
function love.mousepressed(x,y,button,istouch)
    if button == 1 then
        if x >= 50 and x <= 100 then
            if y >=  600 and y <= 700 then
                love.graphics.print("BAZZINGA", 100, 120)
                love.graphics.setColor(0,0,0)
            end 
            if y >=  475 and y <= 495 then
                love.graphics.print("BAZZINGA", 100, 120)
                love.graphics.setColor(100,100,100)
            end 
        end
    end
end

-- love.keypressed(key) where user keyboard input is caught and processed. You see its a bunch of if ifelse conditions, I check the keys
-- I am intrested in then I change the relivant variables depending on what key was pressed. each key gets its own sound. Like I said earlier
-- this code is brittle and difficult to update because its all hardcoded with the soundfiles. The right way to do this is to refer to a
-- configuration table at the start of the program that can be updated by the user from a configuration file. That is the eventual plan. To
-- enable graeter flexability and choice.
-- keybindings should be accessed from a table that can be user defined. That is somthing to fix later. It would make it more flexable and 
-- user friendly.

function love.keypressed(key)

-- arrow keys left and right cycles the menu backwards and forwards.

  if key == "left"  then
    current_screen = (current_screen - 2) % #screens + 1
    TEsound.play("/assets/sounds/Creepy-Roll-Over-3.mp3", "sfx")
  elseif key == "right"  then
    current_screen = current_screen % #screens + 1
    TEsound.play("/assets/sounds/Creepy-Roll-Over-4.mp3", "sfx")
  end

-- f3 increases the sfx volume

    if key == "f3" then
        sfxval = sfxval + 0.1
        if sfxval > 1 then
            sfxval = 1
        end
        TEsound.volume("sfx", sfxval)
        TEsound.play("/assets/sounds/Creepy-Roll-Over-2.mp3", "sfx")
    end

-- f2 decreases the sfx volume

    if key == "f2" then
        sfxval = sfxval - 0.1
        if sfxval < 0 then
            sfxval = 0
        end
        TEsound.volume("sfx", sfxval)
        TEsound.play("/assets/sounds/Creepy-Roll-Over-1.mp3", "sfx")
    end

-- f6 increases the music volume

    if key == "f6" then
        musicval = musicval + 0.1
        if musicval > 1 then
            musicval = 1
        end
        TEsound.volume("music", musicval)
        TEsound.play("/assets/sounds/Creepy-Roll-Over-2.mp3", "sfx")
    end

-- f5 decreases the music volume

    if key == "f5" then
        musicval = musicval - 0.1
        if musicval < 0 then
            musicval = 0
        end
        TEsound.volume("music", musicval)
        TEsound.play("/assets/sounds/Creepy-Roll-Over-1.mp3", "sfx")
    end

-- f4 mutes or unmutes all sounds. 

    if key == "f4" then
        if sfxval and musicval ~= 0 then
            sfxval = 0
            musicval = 0
            TEsound.volume("sfx", sfxval)
            TEsound.volume("music", musicval)
        elseif sfxval and musicval == 0 then
            sfxval = 0.5
            musicval = 0.5
            TEsound.volume("sfx", sfxval)
            TEsound.volume("music", musicval)
        end           
    end

-- the music select key, each time you hit the F8 key you cycle through the playlist.

    if key == "f8" then

       current_music = current_music % 3 +1
       TEsound.stop("music")
       music_list()
       TEsound.playLooping(music_list_choice , "music")
    end

-- finally if the user hits the ESC key it exits the program. Eventually I would have "are you sure you want to quit to desktop?" screen.

    if key == "escape" then
        TEsound.play("/assets/sounds/Creepy-Roll-Over-1.mp3", "sfx")
        love.event.quit()
    end
end
There was an annoying bug in the myJoystick() function, whereby because I just assumed a joystick/gamepad would always be plugged in the program crashed when I removed the device, well a conditional check later it was all good and working fine. Simple mistake fixed.

Looking forward to implementing all the good stuff from MadByte. Today was a good day in terms of progress (by my own humble self assessment anyway..) Will be nice to be able to split the project up into more manageable chucks and really for the first time be able to create a skeleton for the whole project. All of the screens and game-states, all the menus will get a place-holder and I will be able to gradually work my way through each one.

Don't think I will have the whole game in one file, would much prefer to split it up into more manageable chunks.

Looked at dds image encoding after installing the plug in for gimp but from what I can see the images are a fair bit larger than png. So its questionable what benefit I would get in performance for just the menu assets. I think I will save the dds stuff for the more active parts of the program where it might make a difference over png decoding. (like the main program.)

One nice thing about having a old laptop is you never get tempted to mess much with shaders and the like as the graphics card can't support it :)

Still am now thinking about how to implement the main game locations, I was thinking going oldschool and using a table like how a basic program would use an array of 1 and 0 and 2 to determine if a location is possible to travel to. (0 is not possible to move in that direction, 1 is possible and 2 is locked.)

You would then have another array that had a number or string that was used to as a conditional check to branch to that part of the program when position was updated and the screen was redrawn.

Then you would have another array to hold the items, another for npcs ect...

I can remember back in the day a 24x24 array was considered something of a big deal.

Still I think to update this idea instead of having a ton of tables for separate functions I could just use one table of tables with each entry holding all the information about a location in one table.

I would imagine this would have a bit of a performance hit but I can worry about that and split them out into separate tables later if that's the case.

The movement check is pretty straightforward in these old games, you would first check the keyboard to see what direction the player wanted to go, then you would look up the players location, use that to find the position in the path array, if the direction the player wanted to go was a 1 it was all good and you updated the player position to the new location. Otherwise you would error.

How I can do this in the game in lua well thats just updating the gamestate flag/room number depends how its implemented I guess. Not so bad.

Could be top down or side scrolling, or even static screen. The principle is still the same just implemented slightly differently I figure. Anyway that's something to play with tomorrow.
User avatar
Pangit
Party member
Posts: 148
Joined: Thu Jun 16, 2016 9:20 am

Re: My projects and demos

Post by Pangit »

Another day, more progress.

Madbytes example has enabled me to use hump.gamestates in the program. I decided to go with this over my own simplistic state switcher. Well because of the features you get with the library are excellent. Being able to see the working example helped me realise where I was going wrong.

having the various parts of the programs in different files lets me lay out the project in a much more logical and manageable way.

Am busy today planning the overall structure of the program in light of that fact. Will get the skeleton working and update the demo later today.

One little update I want to do today is the metro map. One thing I loved in games was the ability to use a transport system to travel between hubs. an underground or metro system is nice because the design of the stations is usually pretty generic so generating assets is not such a big deal and you can potentially just swap out a few name plates, switch around a few signs ect and you have your stations.

In a city environment you can avoid using a sandbox, and still give the illusion of open world by using a series of hubs connected in this way. Other potential choices are aircraft, boat, or I guess taxi. Anything where the player is not actually driving/directing the vehicle.

Anyway, the metro map is a scene that is dependant on a conditional that looks at the players position within the metro system. That's done by a series of flags contained within a table (I seem to use that a lot..).

The flags get used within the program to trigger sound events like the station name being called, various cut scenes later, AI logic. so while at the moment its just being used to render the map its got a number of other side benefits.

Its an easy scene to implement with a lot of functionality later so its good to do this early.
User avatar
Beelz
Party member
Posts: 234
Joined: Thu Sep 24, 2015 1:05 pm
Location: New York, USA
Contact:

Re: My projects and demos

Post by Beelz »

First, great work! Can't wait to try this game out! :)
Pangit wrote:Anyway, the metro map is a scene that is dependant on a conditional that looks at the players position within the metro system. That's done by a series of flags contained within a table (I seem to use that a lot..).
That is exactly how I used to do things... Over time I found that it is easier to do something like this:

Code: Select all

local locations = {
   city = 'city',
   farm = 'farm',
   bathroom = 'bathroom'
}

local currentLoc = 'city'

-- Sanity check
print(locations[currentLoc])

-- Then you can make a method to trigger things...
function changeLoc(newLoc)
   if locations[newLoc] then
      currentLoc = newLoc
      -- trigger leaving sounds, state change, etc
   else
      print('Location "'..newLoc..'" does not exist!')
   end
end

Code: Select all

if self:hasBeer() then self:drink()
else self:getBeer() end
GitHub -- Website
User avatar
Pangit
Party member
Posts: 148
Joined: Thu Jun 16, 2016 9:20 am

Re: My projects and demos

Post by Pangit »

Thanks for your kind words and your help Beelz. I need to think more about your example - lol its been a long day and my brain is not too quick on the uptake this evening lol.

One thing I am thinking of doing is implementing the blocking function with the hump timer library. So the plan is to allow players to move from station to station only when a train is in the station. I figure the easiest way to implement this is to use a timer that sets a flag that enables a condition check to allow a player to change his location to the next place on the list.

This would remove the need to individually model trains on the network, but still leave the illusion that there was a regular train service. Its possible even to model things like random failures ect with this approach. Just have a random % chance of a failure before the timer event. that would block its execution of the code.

I have the times between trains arrival, time in the station and departure so this should be pretty straight forward.

I always suspected but have confirmed today that Manila's train network is particularly well suited to modelling because most of the stations follow a standard design layout, not like the London underground for instance. So I can use one base station asset and just swap out the signs. This greatly reduces the asset generation time in development while not affecting quality.

I decided to model the planned network for 2020, as the game would be set some time in the future. So that brings the number of stations up. But as I said they all follow a standard design. So its no big deal. Lucky there are a great number of audio recordings of stations and trains so it should be fairly straightforward to get the sound working with TEsound.

Progress has been a bit slow as I had to plan out the various routes that the trains take, what parts of the station needs to be modelled and what can be left out.

Luckily there appears to be extensive documentation on the whole of the network so I can model it as precisely as I needed. I was surprised at that but that's a bonus.

Code: Select all

local farematrix = {NorthAvenue = {NorthAvenue = 0, QuezonAvenue = 13.00, GMAKamuning = 13.00, Cubao = 16.00, SantolanAnapolis = 16.00, Ortigas = 20.00, ShawBoulevard = 20.00, BoniAvenue = 20.00, Guadalupe = 24.00, Buendia = 24.00, Ayala = 24.00, Magalianes = 28.00, TaftAvenue = 28.00}}
This humble acorn of a code snippet - is the first game related programming done on the project!

The stations are all set up (13 in all for the MRT-3), there are no art assets at the moment so your forgive me for not updating the demo but progress wise now have all the various scenes living happy in there own lua files.

Each station has its own farematrix table, it can then be used to subtract the fare from the players or NPC account. I was on the fence about just having a big table with the whole farematrix for all the stations on the line but then I got to thinking a station only needs to know the fares in relation to itself so better to split them up and hide the rest of the data from that station to reduce errors.

Eventually it will populate this table from a central file that I can update, thus not having to edit each station every time I want to adjust the fair matrix. But first just want to get the thing working then worry about making it less brittle to update later.

For game accounting the fares deducted should go somewhere. I should really set up a station account.

Today was the first day I actually worked on game mechanics on this project lol. :o
User avatar
Pangit
Party member
Posts: 148
Joined: Thu Jun 16, 2016 9:20 am

Re: My projects and demos

Post by Pangit »

Another day, another update - the plan is to get the base art asset done for the stations. The MRT-3 has a skeleton layout at the moment. Need to implement opening and closing time of the network and also implement the hump.timer idea I was talking about.

Got the documents, the flow diagrams for the systems in use at the station, art references and also some sound recordings. So its looking good.

First there are 3 types of station. At this stage I will just implement the most common one for the whole of the network. - I can add the other two later.

In the game the stations are basically hubs - you go to these locations and you get to explore a bunch of locations linked to the station. There are vendors in the public section of the station, some NPCs will also congregate there eventually.

With the stations, I am planning to use a library that has the common functions to all stations for each of the stations in the game. That will reduce redundancy and if I need to do something different in one hub I can just use a local overload of that function right?

Tonights update:

Well - to explain the lack of progress, to make a rod for my own back I decided I would like to do an isometric style for the stations. So I have spent the day figuring out how to bend inkscape to my will. (If anyone knows a tool I can use to make isometric / 3d blocks that will work with an integrated (old) laptop that works with linux please feel free to tell me.)
firstiso.png
firstiso.png (46.05 KiB) Viewed 3649 times
First attempt at isometric drawing in inkscape. Lol... Somehow I think the train & station are going to take a little while to create. But on the other hand learning to do this opens up what assets I can create for the game so its probably a good idea to learn it now. Otherwise I am always a slave to what i can find in open game assets ect..
train1.png
train1.png (34.21 KiB) Viewed 3643 times
Here is the very early train asset. Going to change the colours and door design. As you can see the design needs a lot of work, but for a first attempt its ok. At least its enough to act as a place-holder. Next will be the station platform. But that's actually not as difficult as I first though. Will crack on with that tomorrow. Then I will have enough to use in the program for testing. I can always go back and work on the assets later.
User avatar
Pangit
Party member
Posts: 148
Joined: Thu Jun 16, 2016 9:20 am

Re: My projects and demos

Post by Pangit »

Todays update:

Spent most of last night messing around with opengl to see just exactly what the laptop could take as a sanity check before generating a bunch of sub-par isometric assets for the game.

for the curious this was what glxinfo had to say about the laptop..
OpenGL vendor string: Intel Open Source Technology Center
OpenGL renderer string: Mesa DRI Mobile Intel® GM45 Express Chipset
OpenGL version string: 2.1 Mesa 11.2.2
OpenGL shading language version string: 1.20
OpenGL extensions:
OpenGL ES profile version string: OpenGL ES 2.0 Mesa 11.2.2
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 1.0.16
OpenGL ES profile extensions:
Perhaps now you can see the problem with the intel integrated graphics. lol.

Anyway enough of my moaning. I was surprised what could be done with just opengl 2. The modern-tutorials examples and wikibook was fairly interesting. Kind of points to me being able to do basic stuff with regards to shaders ect. But just not anything to fancy. That's something to keep in mind for later. Anyway the outcome to all of this was the situation was not as dire as I first though. Had a little demo running with a 3d cube that was textured. So if opengl can do that it can generate a 3d environment. I just need to now find a tool that uses opengl 2 or lower.

The outcome out of reviewing the opengl code examples is, really I don't want to be doing anything in opengl directly unless someone held a gun to my head. It takes a lot of work to get basic stuff that's pretty trivial on frameworks/libraries like sdl2 ect.. But that said its very fast.

That tutorial series is excellent though. Well worth a look for people interested in opengl.

Still - until I get the funds together for a new machine with a real graphics card, that's the technical limitations I have to deal with. (playing the smallest violin in the world.)

Anyway limitations are a gateway for innovation - I had the idea while I might not be able to use fancy shaders or 3d (that would have been challenging in love anyway..) There was no reason why I couldn't just pre-bake the 3d scenes in another application on a borrowed computer say. Then use them in love. It's a compromise that was used in games like donkey kong country - they pre-rendered the assets in a 3d engine then just used the assets in the game. Giving the illusion that the console was generating the 3d itself. The scenes essentially are on rails at this point but depending on how complicated the player interaction/freedom is its a option for some games. I am pretty sure that's how a lot of games that seemed to have limited 3d worked on the Nintendo DS also.

Back to love - Figured today would be a nice day to add in mouse menu functionality to the character stats part of the program. As yesterday was spent mostly messing with inkscape and opengl. Good to get something concrete accomplished with the project. I will use the SUIT library to do this as it has been very easy to use and stable the last time I tried it. If I get any more time after will combine the character stats menu program with the skeleton main menu/game/stat generator/inventory/config/splash, That will be the first time everything that I was working on would be working together,

Tonight's Update:

Baby steps - but Now have SUIT and mouse support in the character stats menu..

Only issue I am having is I think because of hump.camera and the mouse not realizing the camera has changed position. What I need to do is figure out some way of getting the mouse to alter its position with the SUIT library so that the buttons click properly.

Will post this problem in help and support and see how it goes.

In the mean time, feel free to check out the demo there with the currently broken mouse support. Will update this thread once I get it properly working. I am probably doing something stupid.

https://www.love2d.org/forums/viewtopic.php?f=4&t=82546
Post Reply

Who is online

Users browsing this forum: No registered users and 5 guests