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