Skip to content

Commit

Permalink
First attempt at adding specific support for a background image.
Browse files Browse the repository at this point in the history
  • Loading branch information
neilccbrown committed Dec 7, 2024
1 parent 7fe9006 commit c72c181
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 0 deletions.
49 changes: 49 additions & 0 deletions public/public_libraries/strype/graphics.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import strype_graphics_input_internal as _strype_input_internal
import math as _math
import collections as _collections
import re as _re
import time as _time

def in_bounds(x, y):
Expand Down Expand Up @@ -785,3 +786,51 @@ def key_pressed(keyname):
:return: Either True or False depending on whether the key is currently pressed.
"""
return _collections.defaultdict(lambda: False, _strype_input_internal.getPressedKeys())[keyname]

def set_background(image_or_filename):
"""
Sets the current background image.
The parameter can be an EditableImage, a colour, a filename of an image in Strype's image library, or a URL.
Using a URL requires the server to allow remote image loading from Javascript via a feature
called CORS. Many servers do not allow this, so you may get an error even if the URL is valid and
you can load the image in a browser yourself.
If the background image is smaller than 800x600, it will be tiled (repeated) to fill the area of 800x600.
The background image is always copied, so later changes to an EditableImage will not be shown in the background;
you should call set_background() again to update it.
:param image_or_filename: An EditableImage, an image filename or URL.
"""

# Note we always take a copy, even if the size is fine, because
# we don't want later changes to affect the background:
def background_800_600(image):
dest = EditableImage(800, 600)
w = image.get_width()
h = image.get_height()
horiz_copies = _math.ceil(w / 800)
vert_copies = _math.ceil(h / 600)
# We want one copy bang in the centre, so we need to work out the offset:
# These offsets can be negative if the image is larger than 800x600
x_offset = (800 - w) / 2
y_offset = (600 - h) / 2
for i in range(0, horiz_copies):
for j in range(0, vert_copies):
dest.draw_image(image, x_offset + i * w, y_offset + j * h)
return dest

if isinstance(image_or_filename, EditableImage):
bk_image = background_800_600(image_or_filename)
elif isinstance(image_or_filename, str):
# We follow this heuristic: if it has a dot, slash or colon it's a filename/URL
# otherwise it's a color name/value.
if _re.search(r"[.:/]", image_or_filename):
bk_image = background_800_600(load_image(image_or_filename))
else:
bk_image = EditableImage(800, 600)
bk_image.set_fill(image_or_filename)
bk_image.fill()

_strype_graphics_internal.setBackground(bk_image._EditableImage__image)

3 changes: 3 additions & 0 deletions public/public_libraries/strype/strype_graphics_internal.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ var $builtinmodule = function(name) {
};
return susp;
});
mod.setBackground = new Sk.builtin.func(function(img) {
peaComponent.__vue__.getPersistentImageManager().setBackground(img);
});
mod.addImage = new Sk.builtin.func(function(image, assoc) {
return peaComponent.__vue__.getPersistentImageManager().addPersistentImage(image, assoc);
});
Expand Down
29 changes: 29 additions & 0 deletions src/stryperuntime/image_and_collisions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,47 @@ export const WORLD_WIDTH = 800;
export const WORLD_HEIGHT = 600;

export class PersistentImageManager {
// Special case: 0 is always the background, and inserted first in the map to make it
// first in the iteration order. By default it is an 800x600 white image.
private persistentImages = new Map<number, PersistentImage>();
private persistentImagesDirty = false; // This relates to whether the map has had addition/removal, need to check each entry to see whether they are dirty
private nextPersistentImageId = 0;
private collisionSystem = new System();
// A map to be able to look up the PersistentImage when we find an intersecting Box during collision detection:
private boxToImageMap = new Map<Box, PersistentImage>();

constructor() {
const white_800_600 = new OffscreenCanvas(800, 600);
const ctx = white_800_600.getContext("2d");
if (ctx != null) {
(ctx as OffscreenCanvasRenderingContext2D).fillStyle = "white";
(ctx as OffscreenCanvasRenderingContext2D).fillRect(0, 0, 800, 600);
}
this.persistentImages.set(0, {
id: 0,
img: white_800_600,
x: 0,
y: 0,
rotation: 0,
scale: 1.0,
collisionBox: null,
dirty: true,
associatedObject: null,
});
}

public clear() : void {
this.persistentImages.clear();
this.persistentImagesDirty = false;
this.collisionSystem.clear();
}

public setBackground(imageOrCanvas : OffscreenCanvas) : void {
const bk = this.persistentImages.get(0);
if (bk) {
bk.img = imageOrCanvas;
}
}

// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
public addPersistentImage(imageOrCanvas : HTMLImageElement | OffscreenCanvas, associatedObject?: any): number {
Expand Down

0 comments on commit c72c181

Please sign in to comment.