another color for other tanks

This commit is contained in:
Vinzenz Schroeter 2024-04-16 18:28:09 +02:00
parent 4af51b3e51
commit a0a0762f84
4 changed files with 55 additions and 34 deletions

View file

@ -12,10 +12,3 @@ internal sealed class GamePixel
EntityType = null; EntityType = null;
} }
} }
internal enum GamePixelEntityType : byte
{
Wall = 0x0,
Tank = 0x1,
Bullet = 0x2
}

View file

@ -0,0 +1,8 @@
namespace TanksServer.Graphics;
internal enum GamePixelEntityType : byte
{
Wall = 0x0,
Tank = 0x1,
Bullet = 0x2
}

View file

@ -8,9 +8,13 @@ const pixelsPerRow = 352;
const pixelsPerCol = 160; const pixelsPerCol = 160;
const observerMessageSize = pixelsPerCol * pixelsPerRow / 8; const observerMessageSize = pixelsPerCol * pixelsPerRow / 8;
const isPlayerMask = 1; enum GamePixelEntityType {
Wall = 0x0,
Tank = 0x1,
Bullet = 0x2
}
function getIndexes(bitIndex: number) { function getPixelDataIndexes(bitIndex: number) {
return { return {
byteIndex: Math.floor(bitIndex / 8), byteIndex: Math.floor(bitIndex / 8),
bitInByteIndex: 7 - bitIndex % 8 bitInByteIndex: 7 - bitIndex % 8
@ -23,16 +27,31 @@ function normalizeColor(context: CanvasRenderingContext2D, color: string) {
return context.getImageData(0, 0, 1, 1).data; return context.getImageData(0, 0, 1, 1).data;
} }
function drawPixelsToCanvas({context, width, height, pixels, additional, foreground, background, playerColor}: { function parseAdditionalDataNibble(nibble: number) {
context: CanvasRenderingContext2D, const isPlayerMask = 1;
width: number, const entityTypeMask = 12;
height: number,
pixels: Uint8ClampedArray, return {
additional: Uint8ClampedArray | null, isCurrentPlayer: (nibble & isPlayerMask) != 0,
background: Uint8ClampedArray, entityType: ((nibble & entityTypeMask) >> 2) as GamePixelEntityType,
foreground: Uint8ClampedArray, };
playerColor: Uint8ClampedArray }
}) {
function drawPixelsToCanvas(
{
context, width, height, pixels, additional, foreground, background, playerColor, otherTanksColor
}: {
context: CanvasRenderingContext2D,
width: number,
height: number,
pixels: Uint8ClampedArray,
additional: Uint8ClampedArray | null,
background: Uint8ClampedArray,
foreground: Uint8ClampedArray,
playerColor: Uint8ClampedArray,
otherTanksColor: Uint8ClampedArray
}
) {
let additionalDataIndex = 0; let additionalDataIndex = 0;
let additionalDataByte: number | null = null; let additionalDataByte: number | null = null;
const nextPixelColor = (isOn: boolean) => { const nextPixelColor = (isOn: boolean) => {
@ -45,15 +64,17 @@ function drawPixelsToCanvas({context, width, height, pixels, additional, foregro
if (additionalDataByte === null) { if (additionalDataByte === null) {
additionalDataByte = additional[additionalDataIndex]; additionalDataByte = additional[additionalDataIndex];
additionalDataIndex++; additionalDataIndex++;
info = additionalDataByte; info = parseAdditionalDataNibble(additionalDataByte);
} else { } else {
info = additionalDataByte >> 4; info = parseAdditionalDataNibble(additionalDataByte >> 4);
additionalDataByte = null; additionalDataByte = null;
} }
if ((info & isPlayerMask) != 0) { if (info.isCurrentPlayer)
return playerColor; return playerColor;
}
if (info.entityType == GamePixelEntityType.Tank)
return otherTanksColor;
return foreground; return foreground;
} }
@ -64,7 +85,7 @@ function drawPixelsToCanvas({context, width, height, pixels, additional, foregro
for (let y = 0; y < height; y++) { for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) { for (let x = 0; x < width; x++) {
const pixelIndex = y * pixelsPerRow + x; const pixelIndex = y * pixelsPerRow + x;
const {byteIndex, bitInByteIndex} = getIndexes(pixelIndex); const {byteIndex, bitInByteIndex} = getPixelDataIndexes(pixelIndex);
const isOn = (pixels[byteIndex] & (1 << bitInByteIndex)) !== 0; const isOn = (pixels[byteIndex] & (1 << bitInByteIndex)) !== 0;
const color = nextPixelColor(isOn); const color = nextPixelColor(isOn);
@ -111,10 +132,6 @@ export default function ClientScreen({logout, theme, playerId}: {
if (!drawContext) if (!drawContext)
throw new Error('could not get draw context'); throw new Error('could not get draw context');
const colorBackground = normalizeColor(drawContext, hslToString(theme.background));
const colorPrimary = normalizeColor(drawContext, hslToString(theme.primary));
const colorSecondary = normalizeColor(drawContext, hslToString(theme.secondary));
let pixels = new Uint8ClampedArray(lastMessage.data); let pixels = new Uint8ClampedArray(lastMessage.data);
let additionalData: Uint8ClampedArray | null = null; let additionalData: Uint8ClampedArray | null = null;
if (pixels.length > observerMessageSize) { if (pixels.length > observerMessageSize) {
@ -122,17 +139,16 @@ export default function ClientScreen({logout, theme, playerId}: {
pixels = pixels.slice(0, observerMessageSize); pixels = pixels.slice(0, observerMessageSize);
} }
console.log('', {pixelLength: pixels.length, additionalLength: additionalData?.length});
drawPixelsToCanvas({ drawPixelsToCanvas({
context: drawContext, context: drawContext,
width: canvas.width, width: canvas.width,
height: canvas.height, height: canvas.height,
pixels, pixels,
additional: additionalData, additional: additionalData,
background: colorBackground, background: normalizeColor(drawContext, hslToString(theme.background)),
foreground: colorPrimary, foreground: normalizeColor(drawContext, hslToString(theme.primary)),
playerColor: colorSecondary playerColor: normalizeColor(drawContext, hslToString(theme.secondary)),
otherTanksColor: normalizeColor(drawContext, hslToString(theme.tertiary))
}); });
sendMessage(''); sendMessage('');
}, [lastMessage, canvasRef.current, theme]); }, [lastMessage, canvasRef.current, theme]);

View file

@ -4,6 +4,7 @@ export type Theme = {
primary: HSL; primary: HSL;
secondary: HSL; secondary: HSL;
background: HSL; background: HSL;
tertiary: HSL;
} }
// @ts-ignore // @ts-ignore
@ -68,7 +69,10 @@ export function getRandomTheme(): Theme {
const secondary = getRandomHsl(otherColorParams); const secondary = getRandomHsl(otherColorParams);
primary.h = angle(+1 * goldenAngle + primary.h); primary.h = angle(+1 * goldenAngle + primary.h);
return {background, primary, secondary}; const tertiary = getRandomHsl(otherColorParams);
primary.h = angle(+3 * goldenAngle + primary.h);
return {background, primary, secondary, tertiary};
} }
function applyTheme(theme: Theme) { function applyTheme(theme: Theme) {