import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
import plotly.graph_objects as go
import numpy as np
# Initialize the Dash app
app = dash.Dash(__name__)
# Generate cityscape
def generate_cityscape(length, num_buildings, num_trees):
x = np.linspace(0, length, length)
y = np.zeros_like(x)
buildings = []
for i in range(num_buildings):
start = np.random.randint(0, length - 20)
width = np.random.randint(10, 30)
height = np.random.randint(20, 60)
building_x = [start, start, start + width, start + width, start]
building_y = [0, height, height, 0, 0]
color = 'gray'
if np.random.rand() > 0.5:
color = 'brown'
buildings.append(go.Scatter(
x=building_x, y=building_y,
fill='toself', mode='lines',
line=dict(color=color), fillcolor=color,
showlegend=False
))
# Add windows and doors
num_windows = np.random.randint(2, 5)
for j in range(num_windows):
window_width = width / 4
window_height = height / 5
window_x = start + (j + 1) * (width / (num_windows + 1)) - window_width / 2
window_y = height / 2
buildings.append(go.Scatter(
x=[window_x, window_x, window_x + window_width, window_x + window_width, window_x],
y=[window_y, window_y + window_height, window_y + window_height, window_y, window_y],
fill='toself', mode='lines',
line=dict(color='black'), fillcolor='yellow',
showlegend=False
))
door_width = width / 4
door_height = height / 4
door_x = start + width / 2 - door_width / 2
door_y = 0
buildings.append(go.Scatter(
x=[door_x, door_x, door_x + door_width, door_x + door_width, door_x],
y=[door_y, door_y + door_height, door_y + door_height, door_y, door_y],
fill='toself', mode='lines',
line=dict(color='black'), fillcolor='brown',
showlegend=False
))
trees = []
for i in range(num_trees):
trunk_start = np.random.randint(0, length - 10)
trunk_height = np.random.randint(5, 15)
trunk_width = 2
trunk_x = [trunk_start, trunk_start, trunk_start + trunk_width, trunk_start + trunk_width, trunk_start]
trunk_y = [0, trunk_height, trunk_height, 0, 0]
leaves_radius = 4
leaves_center_x = trunk_start + trunk_width / 2
leaves_center_y = trunk_height + leaves_radius / 2
leaves_x = leaves_center_x + leaves_radius * np.cos(np.linspace(0, 2 * np.pi, 50))
leaves_y = leaves_center_y + leaves_radius * np.sin(np.linspace(0, 2 * np.pi, 50))
trees.append(go.Scatter(
x=trunk_x, y=trunk_y,
fill='toself', mode='lines',
line=dict(color='brown'), fillcolor='brown',
showlegend=False
))
trees.append(go.Scatter(
x=leaves_x, y=leaves_y,
fill='toself', mode='lines',
line=dict(color='green'), fillcolor='green',
showlegend=False
))
road = go.Scatter(x=x, y=y, mode='lines', line=dict(color='black'))
return [road] + buildings + trees
# Generate the man
def generate_man(start_x, running=False):
man_height = 10
man_width = 2
leg_height = 5
leg_width = 1
head_radius = 1
body_x = [start_x, start_x, start_x + man_width, start_x + man_width, start_x]
body_y = [0, man_height, man_height, 0, 0]
leg_x = [start_x + man_width / 2 - leg_width / 2, start_x + man_width / 2 - leg_width / 2,
start_x + man_width / 2 + leg_width / 2, start_x + man_width / 2 + leg_width / 2,
start_x + man_width / 2 - leg_width / 2]
leg_y = [0, leg_height, leg_height, 0, 0]
head_center_x = start_x + man_width / 2
head_center_y = man_height + head_radius
head_x = head_center_x + head_radius * np.cos(np.linspace(0, 2 * np.pi, 50))
head_y = head_center_y + head_radius * np.sin(np.linspace(0, 2 * np.pi, 50))
color = 'blue'
return [
go.Scatter(
x=body_x, y=body_y,
fill='toself', mode='lines',
line=dict(color='black'), fillcolor=color,
showlegend=False
),
go.Scatter(
x=leg_x, y=leg_y,
fill='toself', mode='lines',
line=dict(color='black'), fillcolor='black',
showlegend=False
),
go.Scatter(
x=head_x, y=head_y,
fill='toself', mode='lines',
line=dict(color='black'), fillcolor='peachpuff',
showlegend=False
)
]
# Define cityscape parameters
length = 1000
num_buildings = 50
num_trees = 20
cityscape = generate_cityscape(length, num_buildings, num_trees)
# Define the layout of the Dash app
app.layout = html.Div([
html.H1("Street Fighter", style={'color': 'white', 'textAlign': 'center', 'margin-bottom': '10px', 'font-family': 'ArcadeClassic', 'font-size': '48px'}),
dcc.Graph(id='cityscape-graph', style={'height': '70vh'}),
dcc.Interval(id='interval-component', interval=100, n_intervals=0)
], style={'backgroundColor': 'black', 'padding': '20px'})
# Define the callback to update the visible window of the cityscape
@app.callback(
Output('cityscape-graph', 'figure'),
[Input('interval-component', 'n_intervals')]
)
def update_cityscape(n):
window_size = 50
scroll_speed = 1
start = n * scroll_speed
end = start + window_size
running = np.random.rand() > 0.8 # 20% chance to run
man_x_position = (n * scroll_speed) % length
man = generate_man(man_x_position, running)
fig = go.Figure(data=cityscape + man)
fig.update_layout(
xaxis=dict(range=[start, end], autorange=False, zeroline=False, visible=False),
yaxis=dict(autorange=True, zeroline=False, visible=False),
paper_bgcolor='black',
plot_bgcolor='black',
margin=dict(l=0, r=0, t=0, b=0),
showlegend=False
)
return fig
# Run the app
if __name__ == '__main__':
app.run_server(debug=True)