Fixed ui bugs and made examples better.

This commit is contained in:
Kapendev 2024-12-15 21:08:03 +02:00
parent 381d99461b
commit 25acd69a84
6 changed files with 100 additions and 70 deletions

View file

@ -1,4 +1,12 @@
# Examples
This folder provides example projects to help you get started.
> [!NOTE]
> For examples that use textures, the [atlas.png](atlas.png) file must be downloaded and saved in the project's assets folder.
> If an example uses textures,
> be sure to download the [atlas.png](atlas.png) file and place it in the project's assets folder.
## Example Categories
- [Intro](intro): Basic examples to get familiar with Parin.
- [Games](games): Examples focused on making simple games with Parin.
- [UI](ui): Examples demonstrating how to use the Parin UI toolkit.

View file

@ -1,18 +1,17 @@
/// This example shows how to create a simple game with Parin.
/// This example shows how to create a simple collect-the-coins game with Parin.
import parin;
// The game variables.
auto player = Rect(16, 16);
auto playerSpeed = 120;
auto coins = SparseList!Rect();
auto coinSize = Vec2(8);
auto maxCoinCount = 8;
void ready() {
lockResolution(320, 180);
// Place the player and create the coins. Every coin will have a random starting position.
// Place the player at the center of the window.
player.position = resolution * Vec2(0.5);
// Create the coins. Every coin will have a random starting position.
auto coinSize = Vec2(8);
foreach (i; 0 .. maxCoinCount) {
auto minPosition = Vec2(0, 40);
auto maxPosition = resolution - coinSize - minPosition;
@ -27,24 +26,17 @@ void ready() {
bool update(float dt) {
// Move the player.
auto playerDirection = Vec2();
if (Keyboard.left.isDown || 'a'.isDown) playerDirection.x = -1;
if (Keyboard.right.isDown || 'd'.isDown) playerDirection.x = 1;
if (Keyboard.up.isDown || 'w'.isDown) playerDirection.y = -1;
if (Keyboard.down.isDown || 's'.isDown) playerDirection.y = 1;
player.position += playerDirection * Vec2(playerSpeed * dt);
// Check if the player is touching some coins and remove those coins.
auto playerDirection = Vec2(
Keyboard.right.isDown - Keyboard.left.isDown,
Keyboard.down.isDown - Keyboard.up.isDown,
);
player.position += playerDirection * Vec2(120 * dt);
// Check if the player is touching coins and remove them.
foreach (id; coins.ids) {
if (coins[id].hasIntersection(player)) {
coins.remove(id);
}
if (coins[id].hasIntersection(player)) coins.remove(id);
}
// Draw the game.
foreach (coin; coins.items) {
drawRect(coin);
}
foreach (coin; coins.items) drawRect(coin);
drawRect(player);
if (coins.length == 0) {
drawDebugText("You collected all the coins!", Vec2(8));

View file

@ -1,12 +1,10 @@
/// This example shows how to create a pong-like game with Parin.
import parin;
// The game variables.
auto gameCounter = 0;
auto paddle1 = Rect(2, 25);
auto paddle2 = Rect(2, 25);
auto ball = Rect(5, 5);
auto ballDirection = Vec2(1, 1);
auto ballSpeed = 120;
@ -21,61 +19,52 @@ void ready() {
ball.position = center;
}
// The objects in this game are centered.
// This means that rectangle data is divided into 2 parts, normal and centered.
// A normal rectangle holds the position of an object.
// A centered rectangle is used for collision checking and drawing.
bool update(float dt) {
// The objects in this game are centered.
// This means that rectangle data is divided into 2 parts, normal and centered.
// A normal rectangle holds the position of an object.
// A centered rectangle is used for collision checking and drawing.
// Move the ball.
ball.position += ballDirection * Vec2(ballSpeed * dt);
// Check if the ball exited the screen from the left or right side.
if (ball.centerArea.leftPoint.x < 0) {
ball.position = resolution * Vec2(0.5);
paddle1.position.y = resolutionHeight * 0.5;
paddle2.position.y = resolutionHeight * 0.5;
gameCounter = 0;
} else if (ball.centerArea.rightPoint.x > resolutionWidth) {
if (ball.centerArea.leftPoint.x < 0 || ball.centerArea.rightPoint.x > resolutionWidth) {
ball.position = resolution * Vec2(0.5);
paddle1.position.y = resolutionHeight * 0.5;
paddle2.position.y = resolutionHeight * 0.5;
gameCounter = 0;
}
// Check if the ball exited the screen from the top or bottom side.
if (ball.centerArea.topPoint.y < 0) {
if (ball.centerArea.topPoint.y < 0 || ball.centerArea.bottomPoint.y > resolutionHeight) {
ballDirection.y *= -1;
ball.position.y = ball.size.y * 0.5;
} else if (ball.centerArea.bottomPoint.y > resolutionHeight) {
ballDirection.y *= -1;
ball.position.y = resolutionHeight - ball.size.y * 0.5;
}
// Move paddle1.
paddle1.position.y = clamp(paddle1.position.y + wasd.y * ballSpeed * dt, paddle1.size.y * 0.5f, resolutionHeight - paddle1.size.y * 0.5f);
paddle1.position.y = clamp(
paddle1.position.y + wasd.y * ballSpeed * dt,
paddle1.size.y * 0.5f,
resolutionHeight - paddle1.size.y * 0.5f
);
// Move paddle2.
auto paddle2Target = ball.position.y;
if (ballDirection.x < 1) {
paddle2Target = paddle2.position.y;
}
paddle2.position.y = paddle2.position.y.moveTo(clamp(paddle2Target, paddle2.size.y * 0.5f, resolutionHeight - paddle2.size.y * 0.5f), ballSpeed * dt);
auto paddle2Target = ballDirection.x < 1 ? paddle2.position.y : ball.position.y;
paddle2.position.y = paddle2.position.y.moveTo(
clamp(paddle2Target, paddle2.size.y * 0.5f, resolutionHeight - paddle2.size.y * 0.5f),
ballSpeed * dt
);
// Check for paddle and ball collisions.
// Check for collisions.
if (paddle1.centerArea.hasIntersection(ball.centerArea)) {
ballDirection.x *= -1;
ball.position.x = paddle1.centerArea.rightPoint.x + ball.size.x * 0.5;
gameCounter += 1;
}
if (paddle2.centerArea.hasIntersection(ball.centerArea)) {
ballDirection.x *= -1;
ball.position.x = paddle2.centerArea.leftPoint.x - ball.size.x * 0.5;
gameCounter += 1;
}
// Draw the objects.
// Draw the game.
drawRect(ball.centerArea);
drawRect(paddle1.centerArea);
drawRect(paddle2.centerArea);
// Draw the counter.
auto textOptions = DrawOptions(Hook.center);
textOptions.scale = Vec2(2);
drawDebugText("{}".format(gameCounter), Vec2(resolutionWidth * 0.5, 16), textOptions);

View file

@ -1,7 +1,5 @@
/// This example shows how to use the drag handle.
// TODO: There is a small bug with overlapping UI items. Fix it.
import parin;
auto handlePosition = Vec2(120, 60);
@ -18,7 +16,7 @@ bool update(float dt) {
if (handleOptions.dragLimit) handleOptions.dragLimit = UiDragLimit.none;
else handleOptions.dragLimit = UiDragLimit.viewport;
}
// Create the drag handle and return true if it is dragged.
// Create the drag handle and print if it is dragged.
if (uiDragHandle(Vec2(60), handlePosition, handleOptions)) {
println(handlePosition);
}

View file

@ -11,7 +11,7 @@ void ready() {
bool update(float dt) {
// Set the starting point for subsequent UI items.
setUiStartPoint(Vec2(8));
// Create a button and return true if it is clicked.
// Create a button and print if it is clicked.
if (uiButton(Vec2(80, 30), buttonText)) {
println(buttonText);
}