Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • v-lafeychine/prog-2
1 result
Show changes
Commits on Source (32)
Showing
with 295 additions and 151 deletions
Subproject commit 3bbb2f3adf420cb242b0d25e92871cf4c190dcb4
Subproject commit b3092f4e032092563f9f55129eddf7ca95b12a59
......@@ -3,10 +3,11 @@ scalaVersion := "3.1.1"
enablePlugins(ScalaNativePlugin)
nativeCompileOptions ++= Seq("-stdlib=libc++")
nativeMode := "debug"
nativeLTO := "none"
libraryDependencies ++= Seq(
"org.scalatest" %% "scalatest-funsuite" % "3.2.11" % "test",
"org.scala-lang.modules" %% "scala-swing" % "3.0.0"
)
addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.6.1")
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.6")
addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.4.3")
addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.4.4")
......@@ -7,8 +7,8 @@ let
src = fetchFromGitHub {
owner = "lafeychine";
repo = "CSFML";
rev = "3bbb2f3adf420cb242b0d25e92871cf4c190dcb4";
sha256 = "sha256-3l6jjVpHXJ+dTs6qAHFc/dclaAIzZ1ze3beFqhNpuRI=";
rev = "b3092f4e032092563f9f55129eddf7ca95b12a59";
sha256 = "sha256-bEba6uU/qiL9AcomiablcdvECpp3SgYGcsIL8lyLU2I=";
};
});
llvmPackages = llvmPackages_13;
......
package Main
import SFML.Graphics.{Color, RenderWindow}
import SFML.Graphics.RenderWindow
import SFML.Window.{VideoMode, Window}
val FRAMERATE = 30
@main def main() =
val videoMode = VideoMode(1024, 768, 32)
val window = RenderWindow(videoMode, "Projet", Window.WindowStyle.DefaultStyle)
window.setFramerateLimit(FRAMERATE)
window.setFramerateLimit(30)
window.setVerticalSyncEnabled(true)
val game = Game(window, Scene.Battle.BattleScene)
while window.isOpen() do
window.clear(Color(0, 0, 0, 0))
game.fetchEvents()
game.currentScene.components.foreach(_.update(game))
game.currentScene.components.foreach(_.draw(window))
window.display()
Engine.GameEngine(PokemonGame(), window)
package Main
import Pokemon.*
import Scene.*
import SFML.Graphics.RenderWindow
import SFML.Window.{Event, Mouse}
class Game(window: RenderWindow, private var _currentScene: Scene):
var isTrainerTurn = true
val trainer = Trainer("", List(PokemonFactory("Bulbasaur"), PokemonFactory("Squirtle")), 0)
private var trainerPokemonIndex = 1
val trainerEnemy = Trainer("", List(PokemonFactory("Charmander")), 0)
private var trainerPokemonEnemyIndex = 1
var mouse = (0, 0)
var mouseButtonClicked = false
var queryScene: Option[Scene] = Some(_currentScene)
def currentScene: Scene = _currentScene
def fetchEvents() =
if !isTrainerTurn then
val pokemonTrainerEnemy = trainerEnemy.primaryPokemon.get
val capacity =
pokemonTrainerEnemy.capacity(scala.util.Random.between(0, pokemonTrainerEnemy.capacity.length))
pokemonTrainerEnemy.useCapacity(capacity, trainer.primaryPokemon.get)
this.isTrainerTurn = true
if !trainer.primaryPokemon.get.isAlive then
if trainerPokemonIndex == trainer.numberPokemon then
window.close()
println("Tous tes Pokémons sont hors combat. Fin de partie.")
scala.sys.exit()
trainer.changePrimaryPokemon(trainerPokemonIndex)
trainerPokemonIndex = trainerPokemonIndex + 1
if !trainerEnemy.primaryPokemon.get.isAlive then
if trainerPokemonEnemyIndex == trainerEnemy.numberPokemon then
window.close()
println("Tous les Pokémons adverses sont hors combat. Fin de partie.")
scala.sys.exit()
trainerEnemy.changePrimaryPokemon(trainerPokemonEnemyIndex)
trainerPokemonEnemyIndex = trainerPokemonEnemyIndex + 1
if queryScene.isDefined then
_currentScene.components = List()
_currentScene = queryScene.get
_currentScene.load(this)
queryScene = None
mouseButtonClicked = false
for event <- window.pollEvent() do
event match
case Event.Closed() => window.close()
case Event.MouseMoved(x, y) => mouse = (x, y)
case Event.MouseButtonPressed(Mouse.Button.Left, _, _) => mouseButtonClicked = true
case _ => ()
package Main
import Engine.Game
import Scene.Battle.{Battle, BattleScene}
import Pokemon.{PokemonFactory, Trainer}
val trainer = Trainer("", List(PokemonFactory("Bulbasaur"), PokemonFactory("Squirtle")), 0)
val trainerEnemy = Trainer("", List(PokemonFactory("Charmander")), 0)
/** The instance of the Pokemon game.
*/
class PokemonGame() extends Game(Battle(trainer, trainerEnemy).scene)
package Component
import SFML.Graphics.IntRect
import Component.*
trait Button(size_x: Int, size_y: Int) extends DrawableTexture:
var isHovering = false
def onMouseOver(game: Main.Game): Unit
def onMouseClick(game: Main.Game): Unit
def onMouseExit(game: Main.Game): Unit
def init(): Unit = ()
def update(game: Main.Game): Unit =
val oldHovering = isHovering
val rect = IntRect(pos._1.toInt, pos._2.toInt, size_x * scale, size_y * scale)
isHovering = rect.contains(game.mouse._1, game.mouse._2)
if !oldHovering && isHovering then onMouseOver(game)
if oldHovering && !isHovering then onMouseExit(game)
if isHovering && game.mouseButtonClicked then onMouseClick(game)
package Component
import SFML.Graphics.RenderWindow
trait Drawable():
var color = 255.toByte
var pos = (0.0f, 0.0f)
var scale = 1
def draw(window: RenderWindow): Unit
def init(): Unit
def update(game: Main.Game): Unit
package Component
import SFML.Graphics.{Color, Font, RenderWindow, Text}
import SFML.System.Vector2f
trait DrawableText(font: Font) extends Drawable:
var msg = ""
def draw(window: RenderWindow) =
val text = Text()
text.setFont(font)
text.setString(msg)
text.setColor(Color(color, color, color, 255.toByte))
text.setPosition(Vector2f(pos._1, pos._2))
window.draw(text)
// text.destroy()
package Component
import SFML.Graphics.{Color, IntRect, RenderWindow, Sprite, Texture}
import SFML.System.Vector2f
trait DrawableTexture(texture: Texture) extends Drawable:
var rect: Option[(Int, Int)] = None
def draw(window: RenderWindow) =
val sprite = Sprite(texture)
rect match
case None => ()
case Some(rect) => sprite.setTextureRect(IntRect(0, 0, rect._1, rect._2))
sprite.setPosition(Vector2f(pos._1, pos._2))
sprite.setScale(Vector2f(scale, scale))
sprite.setColor(Color(color, color, color, 255.toByte))
window.draw(sprite)
package Engine
import Objects.Scene
/** Defines what an instance of a game must have.
*/
trait Game(val primaryScene: Scene)
package Engine
import Components.{MonoBehaviour, MouseCollider, Renderer}
import Objects.Scene
import SFML.Graphics.{Color, RenderWindow}
import SFML.Window.{Event, Mouse}
/** Game Engine based on SFML library, based on [[https://unity.com Unity]].
*
* @constructor
* Instantiate the engine with a `game` and initialized `window`.
* @param game
* Instance of a game.
* @param window
* Initialized `window`.
* @return
* Instantiating the engine will never return until the game window closes.
*/
class GameEngine(game: Game, private val window: RenderWindow):
private var currentScene: Scene = game.primaryScene
while window.isOpen() do
window.clear(Color(0, 0, 0, 0))
pollEvent()
currentScene.recursiveComponents[Renderer].sorted.foreach(_.draw(window))
currentScene.recursiveComponents[MonoBehaviour].foreach(_.load(this))
window.display()
/** Change the current scene to `scene`, from next frame.
*
* @param scene
* Scene to load.
*/
def changeScene(scene: Scene): Unit =
currentScene = scene
private def pollEvent(): Unit =
for event <- window.pollEvent() do
event match
case Event.Closed() => window.close()
case event @ Event.MouseMoved(_, _) =>
currentScene.recursiveComponents[MouseCollider].foreach(_.handleMouseEvent(this, event))
case event @ Event.MouseButtonPressed(_, _, _) =>
currentScene.recursiveComponents[MouseCollider].foreach(_.handleMouseEvent(this, event))
case _ => ()
// var isTrainerTurn = true
// val trainer = Trainer("", List(PokemonFactory("Bulbasaur"), PokemonFactory("Squirtle")), 0)
// private var trainerPokemonIndex = 1
// val trainerEnemy = Trainer("", List(PokemonFactory("Charmander")), 0)
// private var trainerPokemonEnemyIndex = 1
// if !isTrainerTurn then
// val pokemonTrainerEnemy = trainerEnemy.primaryPokemon.get
// val capacity =
// pokemonTrainerEnemy.capacity(scala.util.Random.between(0, pokemonTrainerEnemy.capacity.length))
// pokemonTrainerEnemy.useCapacity(capacity, trainer.primaryPokemon.get)
// this.isTrainerTurn = true
// if !trainer.primaryPokemon.get.isAlive then
// if trainerPokemonIndex == trainer.numberPokemon then
// window.close()
// println("Tous tes Pokémons sont hors combat. Fin de partie.")
// scala.sys.exit()
// trainer.changePrimaryPokemon(trainerPokemonIndex)
// trainerPokemonIndex = trainerPokemonIndex + 1
// if !trainerEnemy.primaryPokemon.get.isAlive then
// if trainerPokemonEnemyIndex == trainerEnemy.numberPokemon then
// window.close()
// println("Tous les Pokémons adverses sont hors combat. Fin de partie.")
// scala.sys.exit()
// trainerEnemy.changePrimaryPokemon(trainerPokemonEnemyIndex)
// trainerPokemonEnemyIndex = trainerPokemonEnemyIndex + 1
package Engine
package Components
import Objects.GameObject
trait Component:
var gameObject: GameObject = null
var isActive: Boolean = true
def destroy(): Unit =
gameObject.removeComponent(this)
package Engine
package Components
trait MonoBehaviour extends Component:
private[Engine] var isInitialized: Boolean = false
private[Engine] def load(engine: GameEngine): Unit =
if !isInitialized then { init(engine); isInitialized = true }
update(engine)
def init(engine: GameEngine): Unit
def update(engine: GameEngine): Unit
package Engine
package Components
import SFML.Graphics.FloatRect
import SFML.Window.Mouse
import SFML.Window.Event.{MouseButtonPressed, MouseMoved}
trait MouseCollider(bounds: FloatRect) extends Component:
private var isHovering = false
def handleMouseEvent(engine: GameEngine, event: MouseMoved): Unit =
val MouseMoved(x, y) = event
if bounds.contains(x, y) then
if !isHovering then
onMouseEnter(engine)
isHovering = true
else if isHovering then
onMouseExit(engine)
isHovering = false
def handleMouseEvent(engine: GameEngine, event: MouseButtonPressed): Unit =
event match
case MouseButtonPressed(Mouse.Button.Left, x, y) =>
if bounds.contains(x, y) then onMouseClick(engine)
case _ => ()
def onMouseEnter(engine: GameEngine): Unit
def onMouseClick(engine: GameEngine): Unit
def onMouseExit(engine: GameEngine): Unit
package Engine
package Components
import SFML.Graphics.{Color, FloatRect, IntRect, RenderWindow}
trait Renderer extends Ordered[Renderer], Component:
val bounds = FloatRect()
val color: Color
var layer: RendererLayer
def compare(rhs: Renderer) = layer.depth - rhs.layer.depth
def draw(window: RenderWindow): Unit
package Engine
package Components
class RendererLayer(val depth: Int)
package Engine
package Objects
import Components.{MouseCollider, RendererLayer}
import SFML.Graphics.{FloatRect, Texture}
class Button(texture: Texture, layer: RendererLayer) extends GameObject:
val sprite = addComponent[Sprite](texture, layer)
addComponent[ButtonUI](bounds)
def bounds: FloatRect = sprite.bounds
private class ButtonUI(bounds: FloatRect) extends MouseCollider(bounds):
def onMouseEnter(engine: GameEngine) =
sprite.color.r = 200.toByte
sprite.color.g = 200.toByte
sprite.color.b = 200.toByte
def onMouseClick(engine: GameEngine) = ()
def onMouseExit(engine: GameEngine) =
sprite.color.r = 255.toByte
sprite.color.g = 255.toByte
sprite.color.b = 255.toByte
package Engine
package Objects
import scala.collection.mutable.ListBuffer
import scala.quoted.*
import scala.reflect.*
import Components.Component
import SFML.System.Vector2f
class GameObject private ():
private var _childs: ListBuffer[GameObject] = ListBuffer()
private var _components: ListBuffer[Component] = ListBuffer()
private var _parent: Option[GameObject] = None
private var _pos: Vector2f = Vector2f(0, 0)
private var _scale: Float = 1.0f
def this(pos: Vector2f = Vector2f(0, 0), scale: Float = 1.0f) =
this()
_pos = pos
_scale = scale
def addChild[T <: GameObject](child: T): T =
child._parent = Some(this)
_childs += child
return child
private[Engine] def recursiveChilds: ListBuffer[GameObject] =
val recursiveChilds: ListBuffer[GameObject] = ListBuffer()
for child <- _childs do recursiveChilds ++= (child +: child.recursiveChilds)
return recursiveChilds
def moveTo(pos: Vector2f): this.type = { _pos = pos; this }
inline def translate(translation: Vector2f, frame: Int, callback: () => Unit = () => ()): Unit =
addComponent[Translation](translation, frame, callback)
def parent: GameObject = _parent.get
def pos: Vector2f = _parent match
case Some(parent) => _pos * scale + parent.pos
case None => _pos
def scale: Float = _parent match
case Some(parent) => _scale * parent.scale
case None => _scale
inline def addComponent[T <: Component](inline varargs: Any*): T =
${ GameObject.constructComponent[T]('this, 'varargs) }
def getComponents[T <: Component]()(using TypeTest[Component, T]): ListBuffer[T] =
return _components
.filter(_ match
case x: T => true
case _ => false
)
.asInstanceOf[ListBuffer[T]]
def removeComponent(component: Component): Unit =
_components -= component
object GameObject:
def constructComponent[T <: Component: Type](gameObject: Expr[GameObject], varargs: Expr[Seq[Any]])(using
Quotes
): Expr[T] =
import quotes.reflect.*
val Varargs(args) = varargs
val argsTerm = args.map(_.asTerm).toList
val componentASTConstructor =
Apply(Select(New(TypeTree.of[T]), TypeRepr.of[T].typeSymbol.primaryConstructor), argsTerm).asExprOf[T]
'{
val component = $componentASTConstructor;
component.gameObject = $gameObject;
$gameObject._components += component;
component
}