b
This commit is contained in:
commit
d422608290
BIN
assets/heart.si2
Normal file
BIN
assets/heart.si2
Normal file
Binary file not shown.
127
assets/img2si.py
Normal file
127
assets/img2si.py
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
from array import array
|
||||||
|
from PIL import Image
|
||||||
|
import argparse
|
||||||
|
import io
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
__author__ = "Kuruyia"
|
||||||
|
__version__ = "1.0.0"
|
||||||
|
__license__ = "MIT"
|
||||||
|
|
||||||
|
# The "Simple Image for Space Invaders" (.si2) file format specifications
|
||||||
|
# Authors: Alexandre "Kuruyia" SOLLIER, Marc AMBAUD (2019 - 2020)
|
||||||
|
#
|
||||||
|
# | Address | Length | Description |
|
||||||
|
# |---------|--------|-------------------------------------|
|
||||||
|
# | 0x00 | 2 | Magic number ("SI") |
|
||||||
|
# | 0x02 | 4 | Header magic number ("HEAD") |
|
||||||
|
# | 0x06 | 2 | File version |
|
||||||
|
# | 0x08 | 4 | Pixel count |
|
||||||
|
# | 0x0C | 4 | Image width |
|
||||||
|
# | 0x10 | 4 | Data magic number ("DATA") |
|
||||||
|
# | 0x14 | ??? | Uncompressed image data as RGBA8888 |
|
||||||
|
# "File version", "Pixel count" and "Image width" entries are little-endian, unsigned numbers.
|
||||||
|
|
||||||
|
|
||||||
|
def is_file_si2(filePath):
|
||||||
|
# Check the magic number
|
||||||
|
with open(filePath, 'rb') as file:
|
||||||
|
return file.read(2) == b'SI'
|
||||||
|
|
||||||
|
|
||||||
|
def convert_from_si2(source, output):
|
||||||
|
# Print summary
|
||||||
|
print('Source image: .si2')
|
||||||
|
_, outExtension = os.path.splitext(output)
|
||||||
|
print('Output image: {}'.format(outExtension))
|
||||||
|
|
||||||
|
# Read si2 image data
|
||||||
|
with open(source, 'rb') as file:
|
||||||
|
file.seek(0x08)
|
||||||
|
pixelCount = int.from_bytes(file.read(4), byteorder='little', signed=False)
|
||||||
|
lineSize = int.from_bytes(file.read(4), byteorder='little', signed=False)
|
||||||
|
imageSize = (lineSize, int(pixelCount/lineSize))
|
||||||
|
file.seek(0x14)
|
||||||
|
imageData = file.read()
|
||||||
|
|
||||||
|
# Print summary 2: Electric Boogaloo
|
||||||
|
print('Image size is {}x{}'.format(imageSize[0], imageSize[1]))
|
||||||
|
print()
|
||||||
|
print('Starting conversion...')
|
||||||
|
|
||||||
|
# Save the converted image
|
||||||
|
img = Image.frombytes('RGBA', imageSize, imageData)
|
||||||
|
img.save(output)
|
||||||
|
|
||||||
|
|
||||||
|
def convert_to_si2(source, output):
|
||||||
|
# Print summary
|
||||||
|
_, outExtension = os.path.splitext(source)
|
||||||
|
print('Source image: {}'.format(outExtension))
|
||||||
|
print('Output image: .si2')
|
||||||
|
|
||||||
|
# Read source image
|
||||||
|
with Image.open(source) as img:
|
||||||
|
imageSize = img.size
|
||||||
|
|
||||||
|
if img.mode != 'RGBA':
|
||||||
|
# Convert image mode if unsupported
|
||||||
|
print('Source image mode "{}" is unsupported, attempting conversion...'.format(img.mode))
|
||||||
|
|
||||||
|
imgConvt = img.convert('RGBA')
|
||||||
|
imageData = imgConvt.load()
|
||||||
|
else:
|
||||||
|
imageData = img.load()
|
||||||
|
|
||||||
|
# Print summary 2: Electric Boogaloo
|
||||||
|
print('Image size is {}x{}'.format(imageSize[0], imageSize[1]))
|
||||||
|
print()
|
||||||
|
print('Starting conversion...')
|
||||||
|
|
||||||
|
# Convert the image
|
||||||
|
with open(output, 'wb') as file:
|
||||||
|
file.write(b'SIHEAD\01\00')
|
||||||
|
file.write((imageSize[0]*imageSize[1]).to_bytes(4, byteorder='little'))
|
||||||
|
file.write((imageSize[0]).to_bytes(4, byteorder='little'))
|
||||||
|
file.write(b'DATA')
|
||||||
|
|
||||||
|
for y in range(0, imageSize[1]):
|
||||||
|
for x in range(0, imageSize[0]):
|
||||||
|
file.write(bytes(imageData[x, y]))
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
# Setup argument parser
|
||||||
|
parser = argparse.ArgumentParser(description='This tool converts images compatible with PIL to the minGL 2 Simple Image format (.si2), and vice versa.')
|
||||||
|
parser.add_argument('-v', '--version', action='version', version='%(prog)s 1.0')
|
||||||
|
parser.add_argument('<source image file>', help='The path to the image to convert. A .si2 will be converted to a .png file. Any other image type will be converted to a .si2 file.')
|
||||||
|
parser.add_argument('<output file>', help='The path to output the converted image to.')
|
||||||
|
|
||||||
|
args = vars(parser.parse_args())
|
||||||
|
source = args['<source image file>']
|
||||||
|
output = args['<output file>']
|
||||||
|
|
||||||
|
# Check that source file exists
|
||||||
|
if not os.path.isfile(source):
|
||||||
|
exit('"{}"\nThe specified path does not exist.'.format(source))
|
||||||
|
|
||||||
|
# Check if source file is in the .si2 format
|
||||||
|
isSourceSi2 = is_file_si2(source)
|
||||||
|
|
||||||
|
if isSourceSi2:
|
||||||
|
convert_from_si2(source, output)
|
||||||
|
else:
|
||||||
|
convert_to_si2(source, output)
|
||||||
|
|
||||||
|
print('Done!')
|
||||||
|
|
||||||
|
# with Image.open(source) as img:
|
||||||
|
# for y in range(0, img.height):
|
||||||
|
# for x in range(0, img.width):
|
||||||
|
# print(img.getpixel((x, y)))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
BIN
assets/missile.si2
Normal file
BIN
assets/missile.si2
Normal file
Binary file not shown.
Binary file not shown.
BIN
assets/player2.png
Normal file
BIN
assets/player2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
BIN
assets/player2.si2
Normal file
BIN
assets/player2.si2
Normal file
Binary file not shown.
@ -14,7 +14,7 @@
|
|||||||
#
|
#
|
||||||
general:
|
general:
|
||||||
maxFPS: 30
|
maxFPS: 30
|
||||||
theme:
|
theme: good
|
||||||
|
|
||||||
|
|
||||||
#############################
|
#############################
|
||||||
|
@ -58,6 +58,19 @@ class GoodPixelManager : public PixelManager{
|
|||||||
* @brief sprite of the torpedo
|
* @brief sprite of the torpedo
|
||||||
*/
|
*/
|
||||||
MySprite torpedo;
|
MySprite torpedo;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief sprite of the heart
|
||||||
|
*/
|
||||||
|
MySprite heart;
|
||||||
|
|
||||||
|
void drawInvaderA(const Position& baseVector, unsigned size, const RGBAcolor& color) const override;
|
||||||
|
void drawInvaderB(const Position& baseVector, unsigned size, const RGBAcolor& color) const override;
|
||||||
|
void drawInvaderC(const Position& baseVector, unsigned size, const RGBAcolor& color) const override;
|
||||||
|
void drawPlayer(unsigned x, unsigned width, const RGBAcolor& color) const override;
|
||||||
|
void drawMissile(const Position& baseVector, unsigned width, const RGBAcolor& color) const override;
|
||||||
|
void drawTorpedo(const Position& baseVector, unsigned width, const RGBAcolor& color) const override;
|
||||||
|
void drawHeart(const Position& baseVector) const override;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -98,7 +98,7 @@ public:
|
|||||||
* @param[in] color : color multiplicaror of the invader
|
* @param[in] color : color multiplicaror of the invader
|
||||||
* @fn void drawInvaderA(const Position& baseVector, unsigned size, const RGBAcolor& color) const;
|
* @fn void drawInvaderA(const Position& baseVector, unsigned size, const RGBAcolor& color) const;
|
||||||
*/
|
*/
|
||||||
void drawInvaderA(const Position& baseVector, unsigned size, const RGBAcolor& color) const;
|
virtual void drawInvaderA(const Position& baseVector, unsigned size, const RGBAcolor& color) const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief display a type B invader on screen
|
* @brief display a type B invader on screen
|
||||||
@ -107,7 +107,7 @@ public:
|
|||||||
* @param[in] color : color multiplicaror of the invader
|
* @param[in] color : color multiplicaror of the invader
|
||||||
* @fn void drawInvaderB(const Position& baseVector, unsigned size, const RGBAcolor& color) const;
|
* @fn void drawInvaderB(const Position& baseVector, unsigned size, const RGBAcolor& color) const;
|
||||||
*/
|
*/
|
||||||
void drawInvaderB(const Position& baseVector, unsigned size, const RGBAcolor& color) const;
|
virtual void drawInvaderB(const Position& baseVector, unsigned size, const RGBAcolor& color) const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief display a type C invader on screen
|
* @brief display a type C invader on screen
|
||||||
@ -116,7 +116,7 @@ public:
|
|||||||
* @param[in] color : color multiplicaror of the invader
|
* @param[in] color : color multiplicaror of the invader
|
||||||
* @fn void drawInvaderC(const Position& baseVector, unsigned size, const RGBAcolor& color) const;
|
* @fn void drawInvaderC(const Position& baseVector, unsigned size, const RGBAcolor& color) const;
|
||||||
*/
|
*/
|
||||||
void drawInvaderC(const Position& baseVector, unsigned size, const RGBAcolor& color) const;
|
virtual void drawInvaderC(const Position& baseVector, unsigned size, const RGBAcolor& color) const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief display a player on screen
|
* @brief display a player on screen
|
||||||
@ -125,7 +125,7 @@ public:
|
|||||||
* @param[in] color : color of the plater
|
* @param[in] color : color of the plater
|
||||||
* @fn void drawPlayer(unsigned x, unsigned width, const nsGraphics::RGBAcolor& color) const;
|
* @fn void drawPlayer(unsigned x, unsigned width, const nsGraphics::RGBAcolor& color) const;
|
||||||
*/
|
*/
|
||||||
void drawPlayer(unsigned x, unsigned width, const nsGraphics::RGBAcolor& color) const;
|
virtual void drawPlayer(unsigned x, unsigned width, const nsGraphics::RGBAcolor& color) const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief display a missile on screen
|
* @brief display a missile on screen
|
||||||
@ -134,7 +134,7 @@ public:
|
|||||||
* @param[in] color : color of the missile
|
* @param[in] color : color of the missile
|
||||||
* @fn void drawMissile(const Position& baseVector, unsigned width, const nsGraphics::RGBAcolor& color) const;
|
* @fn void drawMissile(const Position& baseVector, unsigned width, const nsGraphics::RGBAcolor& color) const;
|
||||||
*/
|
*/
|
||||||
void drawMissile(const Position& baseVector, unsigned width, const nsGraphics::RGBAcolor& color) const;
|
virtual void drawMissile(const Position& baseVector, unsigned width, const nsGraphics::RGBAcolor& color) const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief display a torpedo on screen
|
* @brief display a torpedo on screen
|
||||||
@ -143,7 +143,7 @@ public:
|
|||||||
* @param[in] color : color of the torpedo
|
* @param[in] color : color of the torpedo
|
||||||
* @fn void drawTorpedo(const Position& baseVector, unsigned width, const nsGraphics::RGBAcolor& color) const;
|
* @fn void drawTorpedo(const Position& baseVector, unsigned width, const nsGraphics::RGBAcolor& color) const;
|
||||||
*/
|
*/
|
||||||
void drawTorpedo(const Position& baseVector, unsigned width, const nsGraphics::RGBAcolor& color) const;
|
virtual void drawTorpedo(const Position& baseVector, unsigned width, const nsGraphics::RGBAcolor& color) const;
|
||||||
|
|
||||||
#define HEART_LENGTH 40
|
#define HEART_LENGTH 40
|
||||||
|
|
||||||
@ -152,7 +152,7 @@ public:
|
|||||||
* @param[in] baseVector : pixel coordinates of the heart
|
* @param[in] baseVector : pixel coordinates of the heart
|
||||||
* @fn void drawHeart(const Position& baseVector) const;
|
* @fn void drawHeart(const Position& baseVector) const;
|
||||||
*/
|
*/
|
||||||
void drawHeart(const Position& baseVector) const;
|
virtual void drawHeart(const Position& baseVector) const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief display a sprite on screen
|
* @brief display a sprite on screen
|
||||||
|
@ -8,8 +8,37 @@ void GoodPixelManager::loadSprites(vector<Task>& tasks) {
|
|||||||
ADD_SPRITE_TASK(invaderC)
|
ADD_SPRITE_TASK(invaderC)
|
||||||
ADD_SPRITE_TASK(missile)
|
ADD_SPRITE_TASK(missile)
|
||||||
ADD_SPRITE_TASK(torpedo)
|
ADD_SPRITE_TASK(torpedo)
|
||||||
|
ADD_SPRITE_TASK(heart)
|
||||||
}
|
}
|
||||||
|
|
||||||
GoodPixelManager::GoodPixelManager(MinGL& win) : PixelManager(win) {
|
GoodPixelManager::GoodPixelManager(MinGL& win) : PixelManager(win) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GoodPixelManager::drawInvaderA(const Position& baseVector, unsigned size, const RGBAcolor &color) const {
|
||||||
|
drawSprite(invaderA, baseVector);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GoodPixelManager::drawInvaderB(const Position& baseVector, unsigned size, const RGBAcolor &color) const {
|
||||||
|
drawSprite(invaderB, baseVector);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GoodPixelManager::drawInvaderC(const Position& baseVector, unsigned size, const RGBAcolor &color) const {
|
||||||
|
drawSprite(invaderC, baseVector);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GoodPixelManager::drawPlayer(unsigned x, unsigned width, const RGBAcolor& color) const {
|
||||||
|
drawSprite(player, Position(x, getScreenHeight()-PLAYER_HEIGHT));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GoodPixelManager::drawMissile(const Position& baseVector, unsigned width, const RGBAcolor& color) const {
|
||||||
|
drawSprite(missile, baseVector);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GoodPixelManager::drawTorpedo(const Position& baseVector, unsigned width, const RGBAcolor& color) const {
|
||||||
|
drawSprite(torpedo, baseVector);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GoodPixelManager::drawHeart(const Position& baseVector) const {
|
||||||
|
drawSprite(heart, baseVector);
|
||||||
|
}
|
||||||
|
BIN
unconverted_assets/missile.png
Normal file
BIN
unconverted_assets/missile.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.9 KiB |
BIN
unconverted_assets/player.png
Normal file
BIN
unconverted_assets/player.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
Loading…
Reference in New Issue
Block a user