DuCouscous
2 years ago
commit
3fe6eb2dd9
16 changed files with 216 additions and 0 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,28 @@ |
|||
class BlockType: |
|||
NONE = 0 |
|||
STONE = 1 |
|||
WOOD = 2 |
|||
GRASS = 3 |
|||
|
|||
class Block: |
|||
def __init__(self, id: int, durability: int = 0, type: int = BlockType.NONE): |
|||
self.id: int = id |
|||
self.durability: int = durability |
|||
self.type: int = type |
|||
|
|||
|
|||
class BlockAir(Block): |
|||
def __init__(self): |
|||
super().__init__(0) |
|||
|
|||
class BlockStone(Block): |
|||
def __init__(self): |
|||
super().__init__(1, 20, BlockType.STONE) |
|||
|
|||
class BlockDirt(Block): |
|||
def __init__(self): |
|||
super().__init__(2, 10, BlockType.GRASS) |
|||
|
|||
class BlockGrass(Block): |
|||
def __init__(self): |
|||
super().__init__(3, 10, BlockType.GRASS) |
@ -0,0 +1,20 @@ |
|||
import block, perlin |
|||
|
|||
CHUNK_WIDTH = 32 |
|||
CHUNK_HEIGHT = 32 |
|||
|
|||
class Chunk: |
|||
def gen_block(self, x: int, y: int): |
|||
height = int(100 + perlin.noise2d(x, 0.1) * 10) |
|||
|
|||
if y < height: return block.BlockAir() |
|||
if y == height: return block.BlockGrass() |
|||
if y > height and y < height + 4: return block.BlockDirt() |
|||
|
|||
return block.BlockStone() |
|||
|
|||
def get(self, x: int, y: int) -> block.Block(id): |
|||
return self.blocks[x + CHUNK_WIDTH * y] |
|||
|
|||
def __init__(self, x: int, y: int): |
|||
self.blocks = [self.gen_block(i % CHUNK_WIDTH + x * CHUNK_WIDTH, i // CHUNK_WIDTH + y * CHUNK_HEIGHT) for i in range(CHUNK_WIDTH * CHUNK_HEIGHT)] |
@ -0,0 +1,3 @@ |
|||
from renderer import Renderer |
|||
|
|||
Renderer() |
@ -0,0 +1,2 @@ |
|||
all : |
|||
python main.py |
@ -0,0 +1,65 @@ |
|||
import math, random |
|||
|
|||
W = 255 |
|||
H = 255 |
|||
background=(100,100,100) |
|||
gradtable = [ (0,0) for i in range(0,W*H) ] |
|||
|
|||
def precalc_gradtable(): |
|||
rnd = random.Random() |
|||
for i in range(0,H): |
|||
for j in range(0, W): |
|||
x = float((rnd.randint(1,2*W))-W)/W |
|||
y = float((rnd.randint(1,2*H))-H)/H |
|||
s = math.sqrt(x * x + y * y) |
|||
if s!=0: |
|||
x = x / s |
|||
y = y / s |
|||
else: |
|||
x = 0 |
|||
y = 0 |
|||
gradtable[i*H+j] = (x,y) |
|||
|
|||
#calculate dot product for v1 and v2 |
|||
def dot(v1,v2): |
|||
return ( (v1[0]*v2[0]) + (v1[1]*v2[1]) ) |
|||
|
|||
# get a pseudorandom gradient vector |
|||
def gradient(x,y): |
|||
|
|||
# normalize! |
|||
return gradtable[y*H+x] |
|||
|
|||
def s_curve(x): |
|||
return ( 3*x*x - 2*x*x*x ) |
|||
|
|||
def noise2d(x,y): |
|||
|
|||
x0 = math.floor(x) |
|||
y0 = math.floor(y) |
|||
x1 = x0 + 1.0 |
|||
y1 = y0 + 1.0 |
|||
|
|||
i_x0 = int(x0) |
|||
i_x1 = int(x1) |
|||
i_y0 = int(y0) |
|||
i_y1 = int(y1) |
|||
|
|||
s = dot(gradient(i_x0, i_y0),(x-x0, y-y0)) |
|||
t = dot(gradient(i_x1, i_y0),(x-x1, y-y0)) |
|||
u = dot(gradient(i_x0, i_y1),(x-x0, y-y1)) |
|||
v = dot(gradient(i_x1, i_y1),(x-x1, y-y1)) |
|||
|
|||
s_x = s_curve( x - x0 ) |
|||
a = s + s_x*t - s_x*s |
|||
b = u + s_x*v - s_x*u |
|||
|
|||
s_y = s_curve( y - y0 ) |
|||
z = a + s_y*b - s_y*a |
|||
|
|||
return z |
|||
|
|||
def col( a ): |
|||
return int(round((128-(128*a)))) |
|||
|
|||
precalc_gradtable() |
@ -0,0 +1,69 @@ |
|||
import tkinter as tk |
|||
from PIL import Image,ImageTk |
|||
import random |
|||
import threading |
|||
import time |
|||
from world import World |
|||
|
|||
RENDER_WIDTH, RENDER_HEIGHT = 640 // 32 + 1, 480 // 32 + 1 |
|||
FPS = 20 |
|||
|
|||
class Camera: |
|||
def __init__(self, x: int, y: int): |
|||
self.x: int = x |
|||
self.y: int = y |
|||
|
|||
class Renderer: |
|||
def render(self): |
|||
offset_x, offset_y = self.camera.x % 32, self.camera.y % 32 |
|||
index = 0 |
|||
self.world.update_chunks(self.camera.x // 32, self.camera.y // 32) |
|||
for tile in self.tiles: |
|||
self.canvas.moveto(tile, 32 * (index % RENDER_WIDTH)- offset_x, 32 * (index // RENDER_WIDTH) - offset_y) |
|||
self.canvas.itemconfig(tile, image=self.sprites[self.world.get_block( |
|||
self.camera.x // 32 + index % RENDER_WIDTH, |
|||
self.camera.y // 32 + index // RENDER_WIDTH |
|||
).id]) |
|||
index += 1 |
|||
pass |
|||
|
|||
def update_thread(self): |
|||
while self.running: |
|||
self.render() |
|||
self.camera.x += 8 |
|||
time.sleep(1 / FPS) |
|||
pass |
|||
|
|||
def __init__(self): |
|||
self.running = True |
|||
self.window = tk.Tk() |
|||
self.window.title("MC 2D") |
|||
self.window.geometry("640x480") |
|||
|
|||
self.camera = Camera(90 * 32, 90 * 32) |
|||
self.world = World(self.camera.x // 32, self.camera.y // 32) |
|||
|
|||
self.sprites = [ |
|||
"sprites/air.png", |
|||
"sprites/stone.png", |
|||
"sprites/dirt.png", |
|||
"sprites/grass.png" |
|||
] |
|||
|
|||
self.sprites = [ |
|||
ImageTk.PhotoImage(Image.open(sprite)) for sprite in self.sprites |
|||
] |
|||
|
|||
self.canvas = tk.Canvas(self.window, width=640, height=480, background="white") |
|||
self.canvas.pack() |
|||
|
|||
self.tiles = [ |
|||
self.canvas.create_image(32 * (i % RENDER_WIDTH) - 16, 32 * (i // RENDER_WIDTH) - 16, anchor="nw", image=self.sprites[random.randint(0, len(self.sprites) - 1)]) |
|||
for i in range(RENDER_WIDTH * RENDER_HEIGHT) |
|||
] |
|||
|
|||
self.tupdate = threading.Thread(target=self.update_thread) |
|||
self.tupdate.start() |
|||
|
|||
self.window.mainloop() |
|||
self.running = False |
After Width: | Height: | Size: 121 B |
After Width: | Height: | Size: 426 B |
After Width: | Height: | Size: 576 B |
After Width: | Height: | Size: 185 B |
@ -0,0 +1,29 @@ |
|||
from block import Block, BlockAir, BlockStone |
|||
import perlin |
|||
from chunk import Chunk, CHUNK_HEIGHT, CHUNK_WIDTH |
|||
|
|||
class World: |
|||
def __init__(self, x: int, y: int): |
|||
self.chunks = {} |
|||
self.old_x = -1 |
|||
self.old_y = -1 |
|||
self.update_chunks(x, y) |
|||
pass |
|||
|
|||
def update_chunks(self, x: int, y: int): |
|||
x //= CHUNK_WIDTH |
|||
y //= CHUNK_HEIGHT |
|||
if self.old_x == x and self.old_y == y: return |
|||
print("Refresh chunks") |
|||
|
|||
self.chunks = {} |
|||
|
|||
for i in range(x - 1, x + 2): |
|||
for j in range(y - 1, y + 2): |
|||
self.chunks[f"{i}:{j}"] = Chunk(i, j) |
|||
|
|||
self.old_x = x |
|||
self.old_y = y |
|||
|
|||
def get_block(self, x: int, y: int) -> Block: |
|||
return self.chunks[f"{x // CHUNK_WIDTH}:{y // CHUNK_HEIGHT}"].get(x % CHUNK_WIDTH, y % CHUNK_HEIGHT) |
Loading…
Reference in new issue