Here is the alphademo2_01 code.
I commented it for clarity (or obscurity depending on how badly I wrote it..)
Code: Select all
-- alphademo2_01.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 }
-- 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()
icon_nosound_small = love.graphics.newImage("/assets/nosound_small.png")
icon_sound_small = love.graphics.newImage("/assets/sound_small.png")
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 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()
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
-- 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()
local button1down = joysticks[1]:isDown(5)
local button2down = joysticks[1]:isDown(6)
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
-- 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
388 lines of code & comments - result not a great deal. At this rate the total menu system should clock in at around 4-5 K-LOCs.. (4,000 - 5,000 lines.)
When all of the comments, the non-functioning code and white spaces were removed the project clocks in at 0.176 KLOCs (plus libraries).. making the estimate of actual code lines for the final menu system (character stats, character professions, general help, configuration menu, save menu, load menu around 2-3KLOCs.)
Todays task - get the splash screen working.
Update : got the basics sorted. Thanks to the following post.
viewtopic.php?f=4&t=79816&p=181277&hilit=splash#p181277
Now to add the transitions to make it a less abrupt change. Then to split it off in its own function.
Todays update:
I wasted a whole day trying to get hump.gamestate to work.
- error1.jpg (23.18 KiB) Viewed 5104 times
have been looking at this trying to figure out why a skeleton framework wont work..
Code: Select all
gs = require(".lib.hump.gamestate")
lg = love.graphics
local menu = {} -- previously: Gamestate.new()
local game = {}
function menu:draw()
lg.print("Press Enter to continue", 10, 10)
end
function menu:keyreleased(key, code)
if key == 'return' then
gs.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()
gs.registerEvents()
gs.switch(menu)
end
I jiggle the code a bit, see if I have not done something obvious wrong...
- error2.jpg (23.42 KiB) Viewed 5103 times
Code: Select all
gs = require(".lib.hump.gamestate")
lg = love.graphics
local menu = {} -- previously: Gamestate.new()
local game = {}
function menu:draw()
lg.print("Press Enter to continue", 10, 10)
end
function menu:keyreleased(key, code)
if key == 'return' then
gs.switch(game)
end
end
function game:enter()
gs.Entities.clear()
-- setup entities here
end
function game:update(dt)
gs.Entities.update(dt)
end
function game:draw()
gs.Entities.draw()
end
function love.load()
gs.registerEvents()
gs.switch(menu)
end
As a sanity check I went back to the wiki and tried the example code, surprise surprise...
- error3.jpg (17.21 KiB) Viewed 5101 times
Code: Select all
require "lib.hump.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
The amount of time I have wasted I could have just have written a bunch of flags and conditional statements to handle the various game states.