-
Notifications
You must be signed in to change notification settings - Fork 23
Scage methods overview
The basic concept of Scage is "screen". Your scage application consists of one or more screens.
"screen" is some object of a client-defined class which is a child of the Screen class: https://github.com/dunnololda/scage/blob/master/src/main/scala/com/github/dunnololda/scage/ScageScreen.scala#L14
In short it is just a class with a game loop. You can start another game loop from the main screen using the run() method - i.e, run another screen (in your app it could be: open the inventory, help, some kind of menu, etc) then exit from it using the stop() method.
stop()
will stop the current "screen", stopApp()
will stop the whole program. If your program has only one "screen" these are the same.
Screens with entry point have their names end with "App". For example: ScageScreenApp.
Basic developing with Scage is this:
Start new file MyApp.scala (for example)
Write down the import:
import com.github.dunnololda.scage.ScageLib._
This will import everything from Scage.
Then start your object and extend it from ScageScreenApp:
object MyApp extends ScageScreenApp("MyApp", 800, 600) {
ScageScreenApp is a class with game loop, main() method (so it have an entry point) and methods to handle inputs. This will be your main class. When you run it, the window with "MyApp" title and of size 800x600 will be created
Then you write your game logic in action methods to have them executed in a loop. For example:
action {
println("Hello World")
}
This piece of code will add the function () => {println("Hello World")} to the actions queue. All functions from that queue are executed consequentially (according to its pos - see below)
So the program will print "Hello World" to the stdout indefinitely. It will print it exactly 63 times per second no matter how fast your machine is.
This is done by the "smart" game loop. It counts times the actions are executed and all the remains of a second will go to rendering. So rendering will go with any fps, game logic - with 63 fps. If your machine is week, the loop tries to drop rendering fps but keep the game logic fps. Only if rendering decreased to 5 fps, game logic will decreased too.
Optional pos argument - position of your action in the actions queue (similar for preinits, inits, clear, dispose, render, interface). Bigger pos - farther from the start of the queue. This is particularly helpful if you need for example render your main hero sprite above the level floor sprites and above the blood and corpses sprites - you just give "pos = 1" (default pos is 0) to its render function and no matter from where you call it.
Here is the short description of the operation queues:
preinit - will be executed only once, when the screen is started.
init - will be executed every time when the screen is started (it can be restarted again using the restart()
method)
action - your game logic, 63 times per second. or with client-defined fixed period of time if you use actionStaticPeriod
/actionDynamicPeriod
. Also there are actionOnPause
, actionIgnorePause
to handle the "pause" state (enter or leave it using pause()
, pauseOff()
switchPause()
methods). Simple actions will not execute in this state (actionOnPause
, actionIgnorePause
will).
render - opengl render functions, which are applied after the "set center and scale" functions (methods center()
, windowCenter()
, globalScale()
). All basic rendering is done by this functions and you have a convinient way to zoom and move the point of view. For example you can set:
center = your_hero.coord
and your character will always be in the center of the window and everything will be rendered relative to his position.
interface - opengl render functions, which ignore "set center and scale" functions. This is used to write your character HP at the low-left corner and stuff like that.
clear - similar to init, executes every time before the screen stops. With inits this provides a simple tool to restart your game if you need it.
dispose - executes once, when you call stop()
on your screen.
You can also add and remove all kinds of operations in runtime. Remove them using the removeOperation()
method. Also you can remove operation inside the operation itself using the removeSelf()
method.
Inputs are handled similarly with the methods: key
, keyOnPause
, keyIgnorePause
, leftMouse
, rightMouse
, mouseWheelUp
, mouseWheelDown
, mouseMotion
, leftMouseDrag
, rightMouseDrag
(there are also onPause
/ignorePause
variants). For example:
key(KEY_W, onKeyDown = println("Hello World!"))
Will print "Hello World!" to the stdout when you press the 'w' key.
key(KEY_W, onKeyDown = println("Down!"), onKeyUp = println("Up!"))
Will print "Down!" when you press the 'w' key and print "Up!" when you release it.
key(KEY_W, 100, onKeyDown = println("Down!"), onKeyUp = println("Up!"))
Will print "Down!" when you press the 'w' key and will continue to print it every 100 ms until you release it and then print "Up!".
You can also remove and add controls in runtime. Remove them using delControl()
, delControls()
, delAllControls()
, delAllControlsExcept()
methods.