This tutorial assumes you are interested to make games with scala. It will cover all steps you need to compile a project.
Everything you need to install is Simple Build Tool (sbt). With sbt you build your projects, solve dependencies, and do many more stuff. How to install sbt you can read
here. This is everything you need to install, everything else is managed by sbt. Even downloading the scala compiler is done by sbt. For code editing notepad will be sufficient, yet.
now create a folder somewhere on your computer, and open that folder in a terminal. If you have done everything right in the first step, typing
sbt will start sbt and you will be prompted if you want to Create a project. Now you have to enter some project specific details. Name Organisation and Version does not really matter it is only for you, but scala version and sbt version shound not be changed (just hit enter). Now the download of many dependencies starts. After it has finished you should have new folders, and in the terminal you are now in the interactive sbt shell. The most important command you can type here is
run. It compiles and runs your project. To test this, you can create a new source file Main.scala in src/main/scala with the following content:
object Main{
def main(args:Array[String]){
println("Hallo Welt")
}
}
This is just a Hello world program. BTW
~run will automatically compile and run your code every time you save your sourcecode.
For our project we can use the
LWJGL project plugin. Create a file plugin.scala in project/plugin (folder needs to be created) with the following content
import sbt._
class Plugin(info: ProjectInfo) extends PluginDefinition(info) {
val lwjglVersion = "com.github.philcali" % "sbt-lwjgl-plugin" % "2.0.4"
}
this is the plugin definition file. It sets the dependencies to all deeded plugin. If you want to use more plugins for your project, you will have to define them in this file.
Now we also need our project definition, create a file project.scala in project/build (folder needs to be created) with the following content
import sbt._
class Project(info: ProjectInfo) extends LWJGLProject(info)
This is our project definition. there is no project specific configuration yet, because everything we need to run a LWJGL project is inherited by LWJGLProject.
in our sbt terminal we now need to do the folloing two commands
reload
reloads project definitionupdate
downloads dependenciesnow everything is ready to write an LWJGL project. If you are interested how this lwjgl project definition looks like, you can see it in project/plugins/src_managed/sbt-lwjgl-plugin-2.0.4/LWJGLProject.scala. There are also project defitiontions of
Slick and
JMonkey projects, to use them your project definition would look like:
class Project(info: ProjectInfo) extends LWJGLProject(info) with JMonkey
or
class Project(info: ProjectInfo) extends LWJGLProject(info) with Slick2D
to make the home project a little bit more interesting I have created a simple template project that can then be modified into any other project, it is a little bit more than the classic rotating triangle (IKJL for controls). just override your main scala source with:
import org.lwjgl._
import opengl.{Display,GL11,DisplayMode}
import GL11._
import input._
import math._
object Main{
val GAME_TITLE = "My Game"
val FRAMERATE = 60
val width = 640
val height = 480
// init needs to be called before display list of player can be created
init
var finished = false
def main(args:Array[String]){
while(!finished){
Display.update
logic
render
Display.sync(FRAMERATE)
}
}
def init{
println("init Display")
Display.setTitle(GAME_TITLE)
Display.setVSyncEnabled(true)
Display.setDisplayMode(new DisplayMode(width,height))
Display.create
println("init gl")
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
adjustcam
}
def adjustcam{
val v = width.toFloat / height.toFloat
glMatrixMode(GL_PROJECTION)
glLoadIdentity
glFrustum(-v,v,-1,1,1,100)
glMatrixMode(GL_MODELVIEW)
}
def cleanup{
Display.destroy
}
def logic{
import Keyboard._
if(isKeyDown(KEY_ESCAPE))
finished = true
if(Display.isCloseRequested)
finished = true
Player.update
Camera.update
// this rotates our camera around the center
}
def renderGrid(size : Int){
// this creates the nice looking background.
glDisable(GL_LIGHTING)
glBegin(GL_LINES)
for(i <- -size to size){
glVertex2i(i,-size)
glVertex2i(i, size)
glVertex2i(-size,i)
glVertex2i( size,i)
}
glEnd
glEnable(GL_LIGHTING)
}
def render{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Camera.apply
Player.draw
//without background, motion is not visible
// a green grid is nice and retro
glColor3f(0,1,0)
renderGrid(1000)
}
}
object Camera{
var angle = 0.0f
var rotation = 0.0f
def update{
angle += 2.0f % 360
rotation += 0.2f
}
def apply{
glLoadIdentity
glTranslatef(0,0,-20)
glRotatef(-70,1,0,0)
glRotatef(rotation,0,0,1)
}
}
// the player is a singleton, because we only have one player
// if we want to make this game into a multiplayer game, we only need to
// replace object with class, and instanciate some player objects.
object Player
{
// short form to init three variables
var x,y,z = 0f
val vertexData = BufferUtils.createFloatBuffer(18);
val normalData = BufferUtils.createFloatBuffer(18);
vertexData.put(Array[Float](0,0,0.5f, -0.5f,-0.5f,0, -0.5f, 0.5f,0, 0.5f, 0.5f,0, 0.5f,-0.5f,0, -0.5f,-0.5f,0)).flip
normalData.put(Array[Float](0,0, 1, -1 ,-1 ,1, -1 , 1 ,1, 1 , 1 ,1, 1 ,-1 ,1, -1 ,-1 ,1)).flip
val displayList = glGenLists(1)
glEnableClientState(GL_VERTEX_ARRAY)
glEnableClientState(GL_NORMAL_ARRAY)
glVertexPointer(3,0,vertexData)
glNormalPointer(0,normalData)
glNewList(displayList,GL_COMPILE)
glDrawArrays(GL_TRIANGLE_FAN,0,6)
glEndList
glDisableClientState(GL_VERTEX_ARRAY)
glDisableClientState(GL_NORMAL_ARRAY)
def update{
// in scala we can locally import all methods from Keyboard.
import Keyboard._
// rx and rx store our keyboard input as direction
var rx,ry = 0
// keys are IKJL for up down left right
if(isKeyDown(KEY_I))
ry += 1
if(isKeyDown(KEY_K))
ry -= 1
if(isKeyDown(KEY_J))
rx -= 1
if(isKeyDown(KEY_L))
rx += 1
// this makes the direction relative to the camera position
// it is a simple rotation matrix you may know from linear algebra
val ax = rx*cos(-Camera.rotation.toRadians)-ry*sin(-Camera.rotation.toRadians)
val ay = rx*sin(-Camera.rotation.toRadians)+ry*cos(-Camera.rotation.toRadians)
x += 0.1f*ax.toFloat
y += 0.1f*ay.toFloat
}
def draw = {
glPushMatrix
glTranslatef(x,y,z)
glRotatef(Camera.angle, 0, 0, 1.0f)
glColor3f(1, 0, 0)
glCallList(displayList)
glPopMatrix
}
}
ok, thats all about setting up LWJGL. From here on you can edit your code, compile your project and do whatever you want to do. But for syntax highlighting, you should use one of the supported editors. I am using
Gedit, but
Jedit does work as well as the cooperative editor
gobby.
IntelliJ (complete Java IDE) does also work. The good thing is, there is an
sbt plugin that generates the IntelliJ project files for you, and a plugin for IntelliJ (use the plugin manager) that lets you use sbt inside of intelliJ.
(any response even negative response is welcome)