Skip to content

Commit dcf464c

Browse files
GianlucaGianluca
authored andcommitted
Final version
1 parent 76fd0d2 commit dcf464c

File tree

15 files changed

+304
-256
lines changed

15 files changed

+304
-256
lines changed

App.js

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ export default class App extends PureComponent {
99
state = {
1010
winner: 0, // 0: nessuno, 1: giocatore, 2: computer
1111
speed: options.startingGameSpeed,
12-
playerXPosition: width / 2,
13-
lives: 3,
12+
playerXPosition: 0,
13+
lives: options.numberOfLives,
1414
aliens: [],
1515
direction: 1,
1616
down: false,
@@ -66,6 +66,11 @@ export default class App extends PureComponent {
6666
}
6767

6868

69+
exit() {
70+
console.log('Exit')
71+
}
72+
73+
6974
victory() {
7075
clearInterval(this.gameLoop)
7176
this.delay = setTimeout(() => this.initGame(), 500)
@@ -82,7 +87,7 @@ export default class App extends PureComponent {
8287
'GAME OVER',
8388
'Gli alieni hanno vinto!',
8489
[
85-
{ text: 'Esci', onPress: () => console.log('Esci'), style: 'cancel' },
90+
{ text: 'Esci', onPress: () => this.exit(), style: 'cancel' },
8691
{ text: 'Nuova partita', onPress: () => this.initGame() }
8792
],
8893
{ cancelable: false })
@@ -107,8 +112,12 @@ export default class App extends PureComponent {
107112
generateAliens() {
108113
const aliens = []
109114

110-
const xOffset = (width - options.aliensHorSpace * 5) / 2 // per centrare gli alieni
111-
const yOffset = 80
115+
const alienHorSpace = options.alienSize + options.aliensHorDistance
116+
const alienVerSpace = options.alienSize + options.aliensVerDistance
117+
118+
const offsetForCentering = options.aliensHorDistance / 2
119+
const xOffset = offsetForCentering + (width - alienHorSpace * Math.max(...options.aliensInit)) / 2 // Per centrare gli alieni
120+
const yOffset = alienVerSpace + (alienVerSpace * 0.4)
112121

113122
options.aliensInit.map((el, ind) => {
114123
for (let i = 0; i < el; i++) {
@@ -119,8 +128,8 @@ export default class App extends PureComponent {
119128
{
120129
id: `t${type}n${num}`,
121130
t: type,
122-
x: xOffset + (options.aliensHorSpace * i),
123-
y: height - (options.aliensVerSpace * (ind + 1)) - yOffset
131+
x: xOffset + (alienHorSpace * i),
132+
y: height - (alienVerSpace * (ind + 1)) - yOffset
124133
}
125134
)
126135
}
@@ -151,12 +160,12 @@ export default class App extends PureComponent {
151160

152161
// Fuori dallo schermo? Invertire! Controllo solo se gli alieni vanno nella stessa direzione del limite
153162
// per evitare un bug in renderFrame quando si muovono solo verso il basso
154-
if (direction === 1 && el.x + 60 > width || direction === -1 && el.x < 10) {
163+
if (direction === 1 && el.x + (options.alienSize + 16) > width || direction === -1 && el.x < 16) {
155164
this.setState(prevState => ({ direction: prevState.direction *= -1, down: true }))
156165
inversionTrue = true
157166
}
158167

159-
if (el.y <= 50) this.setState({ winner: 2, explosion: [playerXPosition, 0] })
168+
if (el.y <= options.cannonSize) this.setState({ winner: 2, explosion: [playerXPosition, 0] })
160169
})
161170

162171
return clonedAliens
@@ -279,6 +288,7 @@ export default class App extends PureComponent {
279288
lives={lives}
280289
updateLives={this.updateLives}
281290
winner={winner}
291+
exit={this.exit}
282292
/>
283293
)
284294
}

src/components/alien/index.js

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,23 @@
11
import React, { PureComponent } from 'react'
22
import { View, StyleSheet } from 'react-native'
33
import Sprite from '../sprite'
4+
import options from '../../config'
45

56
export default class Alien extends PureComponent {
6-
static defaultProps = {
7-
width: 40
8-
}
97

108
get type() {
119
const { type, variant } = this.props
1210
return `alien${type}_${variant}`
1311
}
1412

1513
render() {
16-
const { width, left, bottom } = this.props
14+
const { left, bottom } = this.props
1715

1816
const dynamicStyles = [styles.base, { left, bottom }]
1917

2018
return (
2119
<View style={dynamicStyles}>
22-
<Sprite image={this.type} width={width} />
20+
<Sprite image={this.type} width={options.alienSize} />
2321
</View>
2422
)
2523
}
@@ -28,8 +26,8 @@ export default class Alien extends PureComponent {
2826
const styles = StyleSheet.create({
2927
base: {
3028
position: 'absolute',
31-
width: 46,
32-
height: 46,
29+
width: options.alienSize,
30+
height: options.alienSize,
3331
alignItems: 'center',
3432
justifyContent: 'center',
3533
//backgroundColor: 'blue'

src/components/aliens-grid/index.js

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import React, { PureComponent } from 'react'
2-
import { StyleSheet } from 'react-native'
32
import Alien from '../alien'
43

54
export default class AliensGrid extends PureComponent {
@@ -26,10 +25,4 @@ export default class AliensGrid extends PureComponent {
2625
render() {
2726
return this.renderAliens()
2827
}
29-
}
30-
31-
const styles = StyleSheet.create({
32-
base: {
33-
//backgroundColor: 'green'
34-
}
35-
})
28+
}

src/components/controls/index.js

Lines changed: 85 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,122 +1,123 @@
11
import React, { PureComponent } from 'react'
2-
import { View, TouchableWithoutFeedback, StyleSheet, PanResponder, Animated } from 'react-native'
2+
import { View, ScrollView, TouchableWithoutFeedback, StyleSheet, Animated, Easing } from 'react-native'
33
import Sprite from '../sprite'
44
import options from '../../config'
55

6+
const cannonHalf = options.cannonSize / 2
7+
68
export default class Controls extends PureComponent {
79
constructor(props) {
810
super(props)
11+
this.scrollView = React.createRef()
12+
this.cannonXPosition = this.props.width / 2
13+
this.translateY = new Animated.Value(0)
14+
this.opacity = new Animated.Value(1)
15+
}
916

10-
this.state = {
11-
width: this.props.width,
12-
translateX: new Animated.Value(0),
13-
}
14-
15-
// coolDown qui per evitare il re-render del componente
16-
this.coolDown = false
17-
this.cannonXPosition = this.state.width / 2
18-
19-
this.cannonRef = React.createRef()
20-
21-
this._panResponder = PanResponder.create({
22-
23-
// Il pan responder è attivo, ma risponde solo allo scrolling (?)
24-
onMoveShouldSetPanResponder: (e, gestureState) => true,
25-
26-
// A inizio scrolling imposta un offset per partire dall'ultima posizione, e non dal centro
27-
onPanResponderGrant: (e, gestureState) => {
28-
this.state.translateX.setOffset(this.state.translateX._value)
29-
},
30-
31-
// Allo scrolling prende il valore dello spostamento sull'asse X, che sarà usato in un transform
32-
onPanResponderMove: (e, gestureState) => {
33-
34-
// Posizione corrente del cannone (il suo centro)
35-
this.cannonRef.current.measure((x, y, elWidth, elHeight, posX, posY) => {
36-
this.cannonXPosition = posX
37-
})
38-
39-
//console.log(this.cannonXPosition)
40-
if (this.cannonXPosition > 25 && this.cannonXPosition < (this.state.width - 25)) {
41-
this.state.translateX.setValue(gestureState.dx)
42-
} else {
43-
//Se va fuori schermo, imposta un dX più o meno pari a metà cannone per riportarlo dentro
44-
//const safeDx = gestureState.dx + (gestureState.dx < 0 ? 25 : -25)
45-
const safeDx = gestureState.dx + (gestureState.dx < 0 ? -25 : -25)
46-
this.state.translateX.setValue(safeDx)
47-
48-
}
49-
//const boundaries = this._calcBoundaries(e.nativeEvent.locationX)
50-
},
51-
52-
// A fine scrolling, aggiunge l'offset al valore finale e lo reimposta a 0
53-
onPanResponderRelease: (e, gestureState) => {
54-
this.state.translateX.flattenOffset()
55-
this.props.updatePlayerPosition(this.cannonXPosition)
17+
componentDidMount() {
18+
const { width } = this.props
19+
// Centra il cannone
20+
// Senza timeout non chiama scrollTo.. perché?
21+
setTimeout(() => this.scrollView.current.scrollTo({ x: width / 2 - cannonHalf, y: 0, animated: false }), 250)
22+
Animated.timing(
23+
this.translateY,
24+
{
25+
toValue: -options.cannonSize,
26+
easing: Easing.bezier(.04, .38, .18, .93),
27+
delay: 200,
28+
duration: 600,
29+
useNativeDriver: true
5630
}
57-
58-
})
31+
).start()
5932
}
6033

34+
componentDidUpdate(prevProps, prevState) {
35+
if (this.props.lives > 0 && prevProps.lives !== this.props.lives) {
36+
Animated.sequence([
37+
Animated.timing(this.opacity, {
38+
toValue: 0.2,
39+
easing: Easing.linear,
40+
duration: 80,
41+
useNativeDriver: true
42+
}),
43+
Animated.timing(this.opacity, {
44+
toValue: 1,
45+
easing: Easing.linear,
46+
duration: 80,
47+
useNativeDriver: true
48+
})
49+
]).start()
50+
}
51+
}
6152

62-
afire = () => {
63-
const { fire, height } = this.props
53+
fire = () => {
54+
const { fire } = this.props
6455

6556
// Passa a fire() la posizione del cannone, per sincronizzare il proiettile
6657
if (!this.coolDown) {
67-
fire({ x: this.cannonXPosition, y: 50 })
58+
fire({ x: this.cannonXPosition, y: options.cannonSize })
6859
this.coolDown = true
6960
setTimeout(() => this.coolDown = false, options.rocketCoolDown)
7061
}
7162

7263
}
7364

65+
calculateCannonPosition(offset) {
66+
const { width, updatePlayerPosition } = this.props
67+
const currentPosition = (width - options.cannonSize) - offset
68+
this.cannonXPosition = currentPosition
69+
// Posizione cannone: offset da inizio schermo a sinista fino a lato sinistro della view
70+
updatePlayerPosition(this.cannonXPosition)
71+
}
72+
7473
render() {
75-
const { translateX } = this.state
76-
const { height, winner } = this.props
74+
const { width, height } = this.props
7775

7876
console.log('Controls rendered')
7977

80-
// Il dx è passato a transform, per traslare la View del valore dx
81-
const animatedStyle = { transform: [{ translateX }] }
78+
const animatedStyle = { transform: [{ translateY: this.translateY }] }
79+
const touchableArea = [styles.innerView, { width: width * 2 - options.cannonSize }]
8280

8381
return (
84-
<View style={[styles.outer, { height: height / 2 }]} {...this._panResponder.panHandlers}>
85-
86-
<View style={styles.inner}>
87-
88-
<Animated.View
89-
style={animatedStyle}
90-
//onLayout={({nativeEvent}) => this.cannonXPosition = nativeEvent.layout.x}
91-
>
92-
<TouchableWithoutFeedback onPress={this.afire}>
93-
<View ref={this.cannonRef}>
94-
{winner !== 2 && <Sprite image='cannon' />}
95-
</View>
96-
</TouchableWithoutFeedback>
97-
</Animated.View>
98-
99-
</View>
100-
101-
</View>
82+
<Animated.View style={[styles.base, { height: height / 2, ...animatedStyle }]}>
83+
<ScrollView
84+
ref={this.scrollView}
85+
horizontal
86+
bounces={false}
87+
showsHorizontalScrollIndicator={false}
88+
overScrollMode='never'
89+
decelerationRate={0.01}
90+
scrollEventThrottle={50}
91+
onScroll={({ nativeEvent }) => this.calculateCannonPosition(nativeEvent.contentOffset.x)}
92+
>
93+
<TouchableWithoutFeedback onPress={this.fire}>
94+
<View style={touchableArea}>
95+
<Animated.View style={[styles.flashView, { opacity: this.opacity }]} >
96+
<Sprite image='cannon' width={options.cannonSize} />
97+
</Animated.View>
98+
</View>
99+
</TouchableWithoutFeedback>
100+
</ScrollView>
101+
</Animated.View >
102102
)
103103
}
104104
}
105105

106106
const styles = StyleSheet.create({
107-
outer: {
108-
//backgroundColor: 'green',
107+
base: {
109108
position: 'absolute',
110-
justifyContent: 'flex-end',
111-
bottom: 4,
109+
bottom: -options.cannonSize,
112110
left: 0,
113-
right: 0,
114111
zIndex: 2
115112
},
116-
inner: {
117-
//backgroundColor: 'red',
118-
height: 40,
119-
justifyContent: 'center',
120-
alignItems: 'center'
113+
innerView: {
114+
//backgroundColor: 'orangered',
115+
flexDirection: 'row',
116+
alignItems: 'flex-end',
117+
justifyContent: 'center'
118+
},
119+
flashView: {
120+
// Senza background, su Android non fa l'animazione alla prima chiamata a CDU (!?)
121+
backgroundColor: 'rgba(0,0,0,0)'
121122
}
122123
})

0 commit comments

Comments
 (0)