I put this together as a simple example of how we can modify the Exploding Chickens mod that was written in Java by CodeName_B for CoderDojo Athenry and then re-written in JavaScript by Kieran Coughlan:
My version does not check that the player has damaged a chicken, but instead checks the entity’s name. If the entity is called “Donald” and you hit it, it will explode in 5 seconds! It does not matter whether Donald is a Villager, a pig, or whatever, and you can have multiple NPCs called Donald and it will work on all of them. (In case you didn’t know, an NPC is a non-player character.)
// Require events
require("events");
// Create a var to represent the bukkit type that represents a player
var bkPlayer = org.bukkit.entity.Player;
// The function which we will run when we load this module
var _loadMod = function()
{
// Announce ourselves to the console
console.log("Exploding Villager ScriptCraft Mod loading");
// Tie our code into the event that fires every time one entity damages another
events.entityDamageByEntity(_entityDamageByEntity);
}
// The code that we want to run each time one entity damages another
var _entityDamageByEntity = function(event)
{
// Find out, from the event, who's getting damaged and who did the damage
var damagedEntity = event.getEntity();
var damagingEntity = event.getDamager();
// If it's a NPC getting damaged by a player, game on...
if (damagedEntity.getCustomName() === "Donald" && damagingEntity instanceof bkPlayer)
{
// Announce in the console that we've detected a player damaging an NPC called Donald
console.log("Exploding Villager - a player damaged an NPC called Donald");
// Schedule a task to run in five seconds (20 * 5 because the Minecraft clock ticks 20 times a second.
server.scheduler.scheduleSyncDelayedTask(__plugin, function()
{
// The original Exploding Chckens mod only triggered if its health went to 0 (killed),
// but let's comment that out so the first hit causes an explosion
//if (damagedEntity.getHealth() - event.getDamage() <= 0)
//{
// Get the NPC's location
var loc = damagedEntity.location;
// Create an explosion at the chicken's location.
// A big one...
loc.world.createExplosion(loc, 10.0);
//}
}, 20 * 5); // end of the command to schedule the task
}
}
// Run this script as soon as the file's loaded
_loadMod();
One of our ninjas was looking for a basic inventory system that he could use, so we knocked up something very quickly.
It’s all based on the standard .NET Dictionary class, documented here.
Dictionary allows us to store keys and associated values. In our specific case, our key is a string (the name of the item) and the value is an int (the count of items of that type).
This is all implemented in a script called InventoryManger.cs which is attached to an empty game object, also called InventoryManagement, for convenience. The InventoryManager class provides the following public methods:
void AddItem(string name)
This takes an item name. It looks to see if there’s an item of this name already in the inventory. If there is, it increases the count by one. If not, it adds it with a count of one. This cannot fail, so it doesn’t return anything.
bool RemoveItem(string name)
This takes an item name. It looks to see if there’s an item of this name in the inventory and that its count is greater than zero; it’s possible that it’s listed there, but the count is zero. If there is, it decreases the count by one and returns true. If not, it returns false. The true/false return value allows us to test, when calling this method, if it succeeded, if that’s important to us.
int GetCount(string name)
This takes an item name. It looks to see if there’s an item of this name in the inventory. If so, it returns its count. If not, it returns zero.
So that allows us to add, remove and track an arbitrary number of items with very little effort.
The sample project also has a few other scripts. The intention is that the player picks up objects by moving over them. Pickup objects are tagged “PickUp”. The HandlePickup.cs script is added to the FPSController to detect moving over a pickup. Pickups have a PickupDetails.cs script attached. This automatically tags them “PickUp” and contains the items name (to use in the inventory). The project also has a FruitStealer.cs which removes one banana from your inventory every time you pass through its gate. It’s just there to show the RemoveItem method in action.
Other small things of note about this project: the “bananas” and “apples” are animated, as is the UI-text containing the text “Fruit Stealer”. The material used for the Fruit Stealer is transparent.
It is belt awarding time at Athenry Coder Dojo! We are really excited to see what everyone is going to come up with this year. In previous years, we have had great projects that use many of the core principles of programming that we have been teaching since the beginning of the year. Here is a list:
MOTION – controlling the movement of a SPRITE by the keyboard, the mouse or randomly by the computer,
LOOPS – using forever or limited repeat blocks to keep something going,
VARIABLES – saving a value in computer memory where the computer can pick it up and use it or change it when necessary,
DECISION blocks – Using IF or IF/THEN blocks to decide if something should happen or not,
BROADCASTS – sending out a message to trigger a reaction in another part of the program,
ANIMATION – using costume edits and changes within loops to make it seem as though a sprite is moving.
You don’t need to use all of the above principles in your project, but we mentors need to know that you understand them in order to let you move up to the next level – Advanced Scratch. While we are helping you with your projects, we will be reinforcing the principles, so it will be fun and easy! The day of the awarding of belts, we will ask you questions on your project while you are demonstrating it.
You must be present on belt award day to show us your projects. If you don’t get the belt you want, don’t worry! There is always the next belt award session and we love having you at Coder Dojo Athenry.
Here are some of the questions we might ask at the belt awards session:
1.Which block you would use to make the sprite speak?
2.How would you change the way your sprite looks?
3.How would you make a sprite move?
4.Can you show where you have used a loop block?
5.Can you show where you have used animation or sound?
6.Can you show us where you have used an IF block?
7.What blocks would you use to check if your sprite hit something?
8.How do you share a program online?
9.Show where you have used a variable or how would you create a new variable?
10.Show where you have used a broadcast or how would you create a new broadcast?
Here are some ideas for projects:
Squash Game
Control a bat to hit a ball
Ball bounces off wall on the other side
Game over when you miss 5 times
ABC Game – letters falling from the sky!
Sprites with A/B/C fall from random start point
Press A/B/C key to stop them
Keep score of how many you stop
DodgeBall –
Have Scratch cat avoid the flying beachballs while he is trying to grab a mouse
Use the arrow keys to control scratch cat and have three or four beachballs fly around randomly
If the cat gets touched by a ball make him lose strength/fade but he gets stronger if he touches a fish.
Use a broadcast to change the backdrop wen he gets his score to ten or to zero.
Good luck and be sure to ask questions! We love to help!
With two more regular dojo sessions to go before our final party and belt awarding ceremony, the finish line’s in sight and we’ve been concentrating on helping people work on their projects.
Some projects are already looking good, and that’s fantastic. Others however aren’t showing a lot of progress.
If you are struggling, please remember – overly ambitious scopes are the things that ruin most game projects. Ask yourself: what are the basic things that will be the most fun in my game? Maybe it’s exploration. Maybe it’s shooting. Whatever it is, get that working as soon as possible. Don’t do ten weapons, do one. Other features can be layered on over time as long as the fundamentals are there. Try hard to have something working for the next session. We’re here to help.
In the next session we’ll talk about the specific belts we’re going to be awarding. We’ll explain how they’re earned and we’ll try to get an idea of how many people are going for each category.
Basic Sample Projects
I briefly showed a number of sample projects that I’d been playing around with this week. These projects are intended to demonstrate certain useful things that you might want to put in your own game.
The first sample project was a modified version of SprocketLeague. The modifications were relatively modest: each car was given its own camera which was set to render into half the screen. The original top-down camera was set to render into a small area at the top of the screen.
The second project, called BasicAI, was just an experiment with baking a NavMesh and having an AI character follow you about. For extra fun, the followers spawn every 1.5s and they’re labeled “HipsterISIS” thanks to a very funny gag one of our ninjas made when watching the game run.
This project wasn’t working fully during our session. It is now. The project contains two scenes. Both implement a door but in different ways. The two scenes can be found in the _scenes folder.
The first implementation is a physics based door. There is a box called DoorFrameRight which has a RigidBody component but is constrained so that it can neither move nor rotate:
Immediately to the left of this is the Door itself. This is also a box with a RigidBody component. In addition, it has a HingeJoint component. This HingeJoint component links it to the DoorFrameRight box. The HingeHoint is just visible as a small orange arrow on the left hand side of this picture:
The HingeJoint component is positioned exactly where the door and door frame meet and its axis is set to be vertical, as the door is to swing around the vertical. It also has a spring which will close the door again (more or less) once the thing pushing it open moves away:
A regular FPSController can’t push this door, as it has a kinematic RigidBody (no physics), so note that we use the RigidBodyFPSController instead to represent the player in this scene.
The other door works in a very different manner. The door consists of a frame and a “hinge”. The hinge is just an empty GameObject which contains all the parts of the door that will be moving. It’s origin is at the left-hand edge of the door panel; this means that when we change the hinge’s Y rotation, the door will pivot about it’s left-hand side. The hinge’s origin is shown here:
I could have made the hinge rotate in code, but instead I decided to create animations to do the same thing (change the hinge’s Y rotation). To explain how animation works in Unity is beyond the scope of this post, but I’ll give a very broad introduction to it in the next session.
The door has a box collider around it. When it detects that the player has entered the collider, it triggers one of the opening animations (the direction depending on which side of the door it determines the player to be). Once the player leaves the collider, it closes the door again.
This project was started live in our last session on the suggestion of one of the ninjas; it generates a random maze using a very simple algorithm.
An empty GameObject called MazeGenerator is placed in the scene. In its Start method, it constructs a random maze which appears in the scene. An FPSController from Standard Assets allows us to navigate this maze and try to find our way out.
The MazeGenerator constructs a 2D array of bool values to represent the maze. All the values in this array are ‘false’ by default and we take this to mean ‘solid’. Taking a point in the centre of the array we mark it ‘true’ to indicate an empty space. We then randomly pick a direction from North, South, East or West and set a new position. We check if we’ve moved outside the bounds of the array yet, if not, we mark this as another empty space and continue until we are outside.
Once we have this maze generated, we know we have a path from the centre (the start) to the exit (the outside of the maze). We loop over all elements in our array and place a solid block (from a prefab) everywhere we find a ‘false’, unless we’re at the edge of the maze in which case we place a special prefab that detect the player and plays a sound. This is our ‘exit’. For a ‘true’ we do nothing. The picture below shows one such generated maze from above.
To make this more fun to play, we also added a script to the FPSController to drop “breadcrumbs” as we move. This shows where we’ve already been so that going around in circles shouldn’t be a problem.
Sorry for not posting for a while, we haven’t covered much new material in the last few weeks.
Today we finally nailed down what our projects are going look like and I think we have some very impressive ideas to work on for the next couple of weeks. By the last session we will be displaying devices like a flood gauge, a food and recipe management system, a retro arcade console, a scalextric racing game timer, a survey/voting machine and a device to help the visually impaired recognise the contents of food cans.
Projects are important for two reasons, they encourage Ninjas to work on their own and they will be the basis for awarding belts.
This year for belts in the Raspberry Pi and Electronics group Ninjas will be examined on more than just code, they will also have to speak about the reason they chose to do the project they did, they will have to explain the various hardware components they used and they will have to create a poster for their project.
I’m looking forward to a busy few weeks in the PiDojo group.