RU beehive logo promo banner for Computing & Info Sciences
CS 380
2025spring
ibarland

hw04: structs
…for Asteroids

Due (at start-of-class):

Standard instructions for all homeworks:


Familiarize yourself with the arcade game Asteroids. We will write our own version, starting with this homework (structs) and finishing with next homework (lists). In our simplified version: We will write a simplified version which only needs to deal with: the ship, asteroids, and bullets. It does not need to deal with: score, number-of-lives, having more than one level, or ufos. For each of the objects which we're modeling, we'll write be writing three functions: how they draw, move, and (only for ships) handle a key-event.

part (a): Racket & Java

  1. Give a Java record and a racket struct for a ship.

    In addition to this datatype-definition, give at least two example ship objects/structs (the design recipe's #2), and the template (the design recipe's #3).

    hint: Thoughts/advice on fields below.

  2. Create (in both racket and Java), a function move-ship which takes in a ship, and returns a ship one tick of time later, ignoring any exterior factors like asteroids or bullets or acceleration/key-presses. Do account for wrapping around the screen; you can (should) have a couple of named-constants for the screen's height and width (perhaps 800x600 or so).

  3. The Java and racket versions should both work in the same way: returning a new object, rather than mutating any fields (Cf. how we wrote enbiggen in both racket and java).

    Note: This method has nothing to do with a gui or drawing. Updating the ship's fields is about the model, not the view. (Later we will write draw-ship below, though in racket-only.)


part (b): Racket only

The following functions only need to be done in Racket (not Java).

  1. Define structs for asteroids or astrs”, and for bullets. (Of course, still complete steps 1-3 of the design recipe.) For each type of data, make four examples-of-the-data: two before versions, and two corresponding after-moving versions. (This will help with test cases.)
  2. Write move-asteroid and move-bullet, similar to move-ship above.
    Note: We will not be using struct-inheritance, so these functions might be very similar to each other. In other games, there are sometime very-different movement rules for the player, enemies, and bullets.
  3. Drawing functions: Write draw-ship : (-> ship? image? image?) which draws a ship onto the provided background-image. Then do similarly for draw-asteroid and draw-bullet.
    notes:
    • The caller might pass any image as the background. For example you can test with , which is exported from videogame-helpers.rkt as house-with-flowers.
    • The library function place-image can be helpful.
  4. Write ship-handle-key, which takes in a ship and a key-event?, and returns a new ship which has processed that key-event.
    notes:
    • Playing the demo above, we see there are only four key-presses that actually do anything in the game. And firing, while it changes the overall world (adds a bullet), doesn't actually change the ship, so this function won't care about firing; we'll handle that next week, when we create an entire world struct.
    • You can compare two key-event?s with string=?, but key=? (from (require 2htdp/universe)) is more appropriate. Equal credit will be awarded, either way.
    • You might want to review notions of distance vs. velocity vs. acceleration; one explanation is at physicsclassroom.com.
    • Note that a key-event never moves the player. Only clock-events (ticks) actually move the player; the key-events are instantaneous in the game-model. However, a key-event can accelerate a player (i.e. change its speed).
  5. Collision detection: Write ship-collide-asteroid?, and asteroid-collide-bullet?, which each return a boolean. We'll ignore asteroids colliding with other asteroids, as well as a ship colliding with bullets (since that's friendly fire).
    Note: You are free to use the provided helper-function overlap? in videogame-helpers.rkt. It takes in any two rectangles; your collision-functions can be a thin wrapper around overlap? by expediently approximating collisions as overlapping bounding boxes of the two objects.
  6. The last piece of single-object behavior we need is when a (non-tiny) asteroid collides with a bullet, and it breaks into 2 or 3 smaller asteroids. Write a function that we can call 2 or 3 times, to generate the smaller asteroids. It should take in one (non-tiny) asteroid, plus some extra bit of info which determines which smaller asteroid is returned. E.g. you might pass in an angle for the new-resulting-asteroid's direction. Myself, I used a vector indicating the new asteroid's acceleration relative to its parent. Next assignment, when we have lists, we'll write a function that takes one (non-tiny) asteroid and returns a list of 2 or 3 smaller asteroids.

For the future…

We still don't have a running game yet. That will entail processing lists of asteroids and lists of bullets. We'll deal with lists on the next homework (as an application of union and structure-types working together, rather than any new concept or syntax!). That's where we'll write code for (say) drawing an entire list of asteroids or list of bullets, as well as an overarching game struct which holds the various pieces of the games (one ship and two other lists).


Design considerations

Fields, in general

Some fields particular to this assignment
  1. My ship had 5 fields: two pairs of numbers, plus another number. There is no image as a field, per invariant above.
  2. One particular thing to think about, before you start coding: Saying a field holds “The location of a ship on-screen” is mildly not-fully-defined: Compare to “the location of Virginia is 37.926868° N, -78.024902° W” -- while admirable to tell me our state's exact location to within 9″, how this value perhaps confusing/unclear? Can you make your field-description for an object's screen-location more precise than just "the object's coordinates in pixels".

Library conventions

Another thing guiding our choices might be the libraries that we want to interact with. In this case, we'll be using the 2htdp/image and 2htdp/universe, so I'll point out the following:


1 In OOP, a class variable or class field is one that's scoped to its class; in Java that's what the keyword static means. It may or may not be public and constant (Java final) as well, like java.lang.Integer#MAX_VALUE.      
2 Computer Graphics experts don't think of pixels as tiny, but rather as very large, with the thing they're trying to draw as a curve passing through that pixel. They then try to compute what single color is the best approximation to the true underlying curve (perhaps even accounting for quirks of how the human eye & psychology works).      

logo for creative commons by-attribution license
This page licensed CC-BY 4.0 Ian Barland
Page last generated
Please mail any suggestions
(incl. typos, broken links)
to ibarlandradford.edu
Rendered by Racket.