-
Notifications
You must be signed in to change notification settings - Fork 0
02 Sprites
For a quick demo, check out the basic-sprite example game.
Adding sprites to a scene is straightforward, the scene's configuration map can specify a :sprites
vector.
(ns quip.foo
(:require [quip.core :as qp]
[quip.utils :as qpu]
[quip.sprite :as qpsprite]))
(defn update-level-01 [state] state)
(defn draw-level-01 [state] (qpu/background [0 43 54]))
(defn scenes []
{:level-01 {:update-fn update-level-01
:draw-fn draw-level-01
;; adding a single image-sprite
:sprites [(qpsprite/image-sprite :player
[100 100]
24
24
"player.png")]}})
(def g (qp/game {:init-scenes-fn scenes
:current-scene :level-01}))
(qp/run g)
Alternatively sprites can be added to or removed from a scene by modifying the :sprites
collection for that scene in any function that returns a new state.
;; this could be in a scene update functions, an input handler, a collision handler etc.
(update-in state
[:scenes :level-01 :sprites]
conj
(qpsprite/image-sprite :enemy
[50 50]
10
10
"enemy.png"))
Sprites have their own update and draw functions, you can invoke them in the scene update and draw functions:
(defn update-level-01
[state]
;; uses the value of `:current-scene` in state to update that scene's sprites
(qpsprite/update-scene-sprites state))
(defn draw-level-01
[state]
(qpu/background [0 43 54])
;; uses the value of `:current-scene` in state to draw that scene's sprites
(qpsprite/draw-scene-sprites state))
There are several ready to use sprites provided by quip. However creating your own sprite is often helpful, especially if you want it to include advanced behaviour.
Custom sprites should be represented by a map, containing at a minimum a :sprite-group
, an :update-fn
and a :draw-fn
.
An image sprite needs a group keyword (used for collision detection, and z-height layers), a position vector, a width, a height, and a filepath for it's image (relative to the resources
directory).
Optionally you can also specify:
(qpsprite/image-sprite
:player
[100 100]
24
24
"player.png"
:rotation 90 ;; rotation in degrees
:vel [-1 1] ;; velocity vector
:update-fn (fn [s] ... ) ;; custom update function
:draw-fn (fn [s] ... ) ;; custom draw function
:points [[0 0] ... ] ;; list of points describing bounding polygon
:bounds-fn (fn [s] ... ) ;; custom bounds function
)
The default update function modifies the sprite position based on its velocity, the default draw function draws the sprite image to the scene. The default bounding function (used for collision detection) returns a rectangle based on the sprites width and height unless :points
are specified in which case it will return the polygon they describe. Specifying :bounds-fn
will override the default bounding function and should return a set of points describing a polygon.
The animated-sprite
function is slightly more complex as it takes a spritesheet image (rather than a single image) and an optional :animations
configuration map describing the animations found in the spritesheet (each animation should be a row in the spritesheet). The animation configuration map should detail each animation, specifying :frames
(the number of frames in this animation), :y-offset
(zero-indexed position from the top of the sheet, with the unit being the sprite's height) and :frame-delay
(the number of game frames to wait before moving to the next animation frame). Finally, the sprite should also specify the :current-animation
.
(qpsprite/animated-sprite
:player
[100 100]
24
24
"player-spritesheet.png"
:animations {:idle {:frames 4
:y-offset 0
:frame-delay 15}
:run {:frames 4
:y-offset 1
:frame-delay 8}
:jump {:frames 7
:y-offset 2
:frame-delay 8}}
:current-animation :idle)
The text-sprite
function requires the text to display and the position. It takes several optional arguments, such as :font
, :size
, :color
and :offsets
.
(qpsprite/text-sprite
"Super Cool Game"
[200 150]
:font "Ubuntu Mono Italic" ;; font must exist
:size 32 ;; font height in pixels
:color [255 0 0] ;; [R G B] colour
:offsets [:left :center]) ;; alignment offsets
The :offsets
field is a vector of one or two keywords. If a single keyword it will apply to both x and y (e.g. [:center]
), if two keywords they will apply to the x and y axis respectively (e.g. [:left :top]
). This field defaults to [:center]
.
The font being used for a text-sprite
must exist on the end user's system. To ensure this you can add the <font>.tff
file to your resources
directory and add the font to the game state during setup using Quil's create-font
function.
(defn setup
[]
{:font (quil.core/create-font "UbuntuMono-Italic.ttf"
quip.utils/default-text-size)})