#+HTML_HEAD:
#+HTML_HEAD:
#+title: Lesson 11 - Creating the first enemy
[[../../arpg/toc.org][< Back to Main TOC]]
* Notes
** Create a New Sprite
*** add the nodes
1. Make a new scene
2. Add a CharacterBody2D node
3. to the new characterbody node, add a AnimatedSprite2D node
*** add animations node
1. add the sprite sheet to the project ./art
2. go to AnimatedSprite2D node-> Animated Sprite2D -> Animation-> Sprite Frames
a) click where it says empty, and select New Sprite Frames
b) now click inside "New sprite Frames", this will open up the SpriteFrames editor at the bottom
c) The options will be Animations and Animations Frames
*** add sprite sheet
1. click on 'default' in the animations section on the left side of the SpriteFrames editor
#+ATTR_HTML: :width 300px
[[../../_share/media/img/select animation.png]]
2. change name of the animation from 'default' to a name describing the animation
3. now click on the 'add frames from sprite sheet icon' in the Animations Frame panel of the
Sprite Frame Editor
#+ATTR_HTML: :width 500px
[[../../_share/media/img/add frames.png]]
- select the sprites you want to add and hit the Add button
- elements of the add frames
- horizontal and vertical determines rows and columns in spritesheet
- size determines pixel sizes
4. click on the 'new animation' button to add another animation and repeat the process above
#+ATTR_HTML: :width 300px
[[../../_share/media/img/add new animation.png]]
*** Reposition the Sprite
- this is important for y-sorting
- in the scene, select and move the sprite above the x-axis
see how the animation looks by going to AnimatedSprite2D-> Animation
choose from the dropdown in Animation to pick which animation you want
incrase or decrease the Frame number for the correct frame
*** add to world map
- save as whatever name you want
- switch to world scene
- add the sprite into the same layer area as the player
** make the sprite movable
- add a new script on the root node of the sprite
- erase everything in script except for extends CharacterBody2D at the top
*** =func _ready=
- Vector2(0, 3*16)
- 16 is the height of the sprite
- 3 is how many sprites spaces we move
- startPosition: where the sprite starts at
- endPosition: about 3 sprite lengths up
*** =func changeDirection=
- switch end and start positions
- this way it will regard as what was the end as the new start
*** =func updateVelocity=
- moveDirection: we compare where we have to go 'endPosition' to where we CURRENTLY ARE 'position'
- compare current position to goal position
- get difference
- use the normalization of the difference to find the direction =moveDirection.normalized=
- use the length of the difference to find if we hit the limit of how far we need to go =moveDirection.length < limit=
- =moveDirection.length < limit=: if so, change the direction as above
- =velocity = moveDirection.normalized * speed=:
- normalize the moveDirection so we get the direction alone
- multiple it by how far the sprite is expected to move at any given time
*** full script
#+begin_src gdscript
extends CharacterBody2D
@export var speed = 20
@export var limit = 0.5
var startPosition
var endPosition
func _ready():
startPosition = position
endPosition = startPosition + Vector2(0, 3*16)
func changeDirection():
var tempEnd = endPosition
endPosition = startPosition
startPosition = tempEnd
func updateVelocity():
var moveDirection = (endPosition - position)
if moveDirection.length() < limit:
changeDirection()
velocity = moveDirection.normalized() * speed
func _physics_process(delta: float) -> void:
updateVelocity()
move_and_slide()
#+end_src
** update the sprite-moving-script.gd
*** at beginning of script add: =@onready var animations = $AnimatedSprite2D=
1. =@onready=
- The =@onready= keyword tells Godot to initialize the variable after the node is added to the scene tree. Normally, if you try to access nodes in the scene tree during the script's initialization (before they're fully ready), you might get errors because those nodes don't exist yet.
- With =@onready=, the variable animations will be initialized once the node and its children have been added to the scene tree, ensuring it's ready to be used when the scene starts running.
2. =var animations=
- creates a variable named 'animations'
3. =$AnimatedSprite2D=
- The =$= symbol is a shortcut in Godot's GDScript to quickly reference child nodes in the scene tree. In this case, =$AnimatedSprite2D= accesses the AnimatedSprite2D node that is a child of the current node the script is attached to.
- =AnimatedSprite2D= refers to the specific node in your scene that handles sprite animations. It has functionalities such as starting, stopping, and switching animations.
*** func updateAnimation
- create a variable to hold the name of the animation you decide to play
- change this value based on the velocity of the sprite
- e.g. - if the velocity is greater than 0 set the animation to "walkDown"
- at the end of the function
- refer to whatever variable is set to your =$AnimatedSprite2D= objct
- call it's play function and pass the name of the animation you want to play
- e.g. =animations_node.play(animation_string_name)=
- make sure to call this function from the physics process!!!
** set end position to world scene marker
*** add marker 2D node to sprite
- go to world scene
- right click on sprite
- add a Marker2D node
- the marker pointer will be right on the sprite if you scroll in
- grab the marker crosshair and move it to where you want
*** add Marker2D to the sprite script
- =@export var endPoint: Marker2D=
- add an export variable
- specify the type is Marker2D
*** assign Marker2D to endpoint
- the Sprite inspector will now show an EndPoint property
- select the sprite
#+ATTR_HTML: :width 300px
[[../../_share/media/img/sprite-endpoint.jpg]]
- go to world, and drag the Marker2D object to the EndPoint property in the inspector for sprite
#+ATTR_HTML: :width 300px
[[../../_share/media/img/marker2d-world.jpg]]
- if you drag over the sprite object, then inspector will open up on that and you can move it over
*** in func _ready
- set endPosition to the global position of the endPoint marker
- global position is the actual position in the game
- regular position is relative to teh nodes parents' position
- =endPosition = endPoint.global_position=
* Video Contents
#+attr_html: :class content
- [[https://youtu.be/2oPzZqHR2Rg?si=VHsayee8NVDr4Ry9][00:00 Introduction]]
- [[https://youtu.be/2oPzZqHR2Rg?si=GG2BcV0rhJ4b8epF&t=19][00:19 enemy scene]]
- [[https://youtu.be/2oPzZqHR2Rg?si=9We59c3XSGKbWlEi&t=60][00:59 AnimatedSprite2D]]
- [[https://youtu.be/2oPzZqHR2Rg?si=C1mylGzZtosFZUwB&t=98][01:38 animations]]
- [[https://youtu.be/2oPzZqHR2Rg?si=OIq3oYJ5AWk41DsJ&t=194][03:15 add to world]]
- [[https://youtu.be/2oPzZqHR2Rg?si=CQexlsKAtUi8uFeQ&t=253][04:13 pixel snap]]
- [[https://youtu.be/2oPzZqHR2Rg?si=h97wsBEmojFO60rR&t=271][04:32 enemy movement]]
- [[https://youtu.be/2oPzZqHR2Rg?si=G5EvLXmC91RYUXaV&t=446][07:26 change direction]]
- [[https://youtu.be/2oPzZqHR2Rg?si=gPMPsk_CtNiMG485&t=506][08:27 update animation]]
- [[https://youtu.be/2oPzZqHR2Rg?si=EKWIowl3pqQ7UKY3&t=545][09:05 adding variation]]
- [[https://youtu.be/2oPzZqHR2Rg?si=-oNx4SQg639T0b0N&t=608][10:08 outro]]